您的位置:首页 > 编程语言 > C语言/C++

vb般的VC++开发(4)--调用IDispatch接口的属性和方法

2008-08-01 17:17 766 查看
前面我们说过vb不仅支持一般的接口方法调用,还支持通过IDispatch接口进行自动化调用。通过#import,VC可以很好的支持一般的接口调用,但对IDispatch接口没有提供直接的支持。为了能方便的调用IDispatch接口,我们需要自己开发一个辅助类。我们先看一个例子:我们通过IDispatch接口调用IProvider接口中的属性和方法

__interface IProvider: IDispatch

{

[id(1),propget] HRESULT Value([out,retval] BSTR* pbstrValue);

[id(1),propput] HRESULT Value([in] BSTR bstrValue);

[id(2)] HRESULT Echo([in] BSTR bstrMessage1, [out,retval] BSTR* pbstrMessage2);

};

vb

'获取属性值

sValue=oDispatch.Value

'设置属性值

oDispatch.Value=sValue

'调用方法

sMessage2=oDispatch.Echo("hello world!")

vb般的vc++

//获取属性值

_bstr_t bstrValue=CVB::get(pDispatch,L"Value");

//设置属性值

CVB::put(pDispatch,L"Value",bstrValue);

//调用方法

_bstr_t bstrMessage2=CVB::Invoke1( pDispatch, L"Echo", L"hello world!");

下面是CVB类的源代码,你也可以从CSDN资源直接下载

http://download.csdn.net/source/566053

/* CVB by Kevin

Version 1.0 (2008-08-01)

----------------------------------------

email: heart@pimshell.com

homepage: http://www.pimshell.com
License

-------

Feel free to use this class, as long as you don't claim that you wrote it

and this copyright notice stays intact in the source files.

If you use this class in commercial applications, please send a short message

to heart@pimshell.com

Version history

---------------

- 1.0 initial release

*/

#pragma once

#include <dispex.h>

///////////////////////////////////////////

__declspec(selectany) VARIANT vtEmpty={VT_EMPTY};

__declspec(selectany) VARIANT vtNull={VT_NULL};

///////////////////////////////////////////

#define DISPATCH_METHOD_EX 0x10

///////////////////////////////////////////

#define __SAFECALL_BEGIN /

try{/

#define __SAFECALL_END /

/

}/

catch(_com_error& e){/

return e.Error();/

}/

catch(...){/

return E_FAIL;/

}/

return S_OK

//////////////////////////////////////////

class CVB

{

public:

static _variant_t get(IDispatch* pDisp,LPCTSTR szMemberName)

{

return Invoke0(pDisp,szMemberName,DISPATCH_PROPERTYGET);

}

static void put(IDispatch* pDisp,LPCTSTR szMemberName,const _variant_t & vParam1)

{

Invoke1(pDisp,szMemberName,vParam1,DISPATCH_PROPERTYPUT);

}

//invoke with no params.

static _variant_t Invoke0(IDispatch* pDisp,LPCTSTR szMemberName,int autoType=-1)

{

CString sMemberName;

int nAutoType=__CheckAutoType(szMemberName,autoType,sMemberName);

_variant_t vResult;

_com_util::CheckError(__AutoWrap(nAutoType,FALSE,&vResult,pDisp,(LPCTSTR)sMemberName,0));

return vResult;

}

static _variant_t Invoke1(IDispatch* pDisp,LPCTSTR szMemberName,const _variant_t & vParam1,int autoType=-1)

{

CString sMemberName;

int nAutoType=__CheckAutoType(szMemberName,autoType,sMemberName);

_variant_t vResult;

_com_util::CheckError(__AutoWrap(nAutoType,FALSE,&vResult,pDisp,(LPCTSTR)sMemberName,1,vParam1));

return vResult;

}

static _variant_t Invoke2(IDispatch* pDisp,LPCTSTR szMemberName,const _variant_t & vParam1,const _variant_t & vParam2,int autoType=-1)

{

CString sMemberName;

int nAutoType=__CheckAutoType(szMemberName,autoType,sMemberName);

_variant_t vResult;

_com_util::CheckError(__AutoWrap(nAutoType,FALSE,&vResult,pDisp,(LPCTSTR)sMemberName,2,vParam1,vParam2));

return vResult;

}

static _variant_t Invoke3(IDispatch* pDisp,LPCTSTR szMemberName,const _variant_t & vParam1,const _variant_t & vParam2,const _variant_t & vParam3,int autoType=-1)

{

CString sMemberName;

int nAutoType=__CheckAutoType(szMemberName,autoType,sMemberName);

_variant_t vResult;

_com_util::CheckError(__AutoWrap(nAutoType,FALSE,&vResult,pDisp,(LPCTSTR)sMemberName,3,vParam1,vParam2,vParam3));

return vResult;

}

static _variant_t Invoke4(IDispatch* pDisp,LPCTSTR szMemberName,const _variant_t & vParam1,const _variant_t & vParam2,const _variant_t & vParam3,const _variant_t & vParam4,int autoType=-1)

{

CString sMemberName;

int nAutoType=__CheckAutoType(szMemberName,autoType,sMemberName);

_variant_t vResult;

_com_util::CheckError(__AutoWrap(nAutoType,FALSE,&vResult,pDisp,(LPCTSTR)sMemberName,4,vParam1,vParam2,vParam3,vParam4));

return vResult;

}

static _variant_t Invoke5(IDispatch* pDisp,LPCTSTR szMemberName,const _variant_t & vParam1,const _variant_t & vParam2,const _variant_t & vParam3,const _variant_t & vParam4,const _variant_t & vParam5,int autoType=-1)

{

CString sMemberName;

int nAutoType=__CheckAutoType(szMemberName,autoType,sMemberName);

_variant_t vResult;

_com_util::CheckError(__AutoWrap(nAutoType,FALSE,&vResult,pDisp,(LPCTSTR)sMemberName,5,vParam1,vParam2,vParam3,vParam4,vParam5));

return vResult;

}

static int __CheckAutoType(LPCTSTR szMemberName,int autoType,CString& sMemberName)

{

int nAutoType;

//

sMemberName=szMemberName;

//

if(autoType!=-1)

{

nAutoType=autoType;

}

else

{

int nPos=sMemberName.Find(L'=');

if(nPos==-1)

{

nAutoType=DISPATCH_METHOD;

//nAutoType=DISPATCH_PROPERTYGET | DISPATCH_METHOD;

}

else if(nPos==0)

{

nAutoType=DISPATCH_PROPERTYGET;

sMemberName.TrimLeft(L'=');

}

else

{

nAutoType=DISPATCH_PROPERTYPUT;

sMemberName.TrimRight(L'=');

}

}

return nAutoType;

}

//

static HRESULT __AutoWrap(int autoType, BOOL CanIgnore, VARIANT *pvResult, IDispatch *pDisp,

LPCTSTR ptName, int cArgs...)

{

// Begin variable-argument list...

va_list marker;

va_start(marker, cArgs);

HRESULT hr=__AutoWrap(autoType,CanIgnore,pvResult,pDisp,(LPOLESTR)ptName,cArgs,marker);

// End variable-argument section...

va_end(marker);

return hr;

}

//

static HRESULT __AutoWrap(int autoType, BOOL CanIgnore, VARIANT *pvResult, IDispatch *pDisp,

LPOLESTR ptName, int cArgs,va_list& marker)

{

//

if(!pDisp) {

return E_FAIL;

}

HRESULT hr;

//

DISPPARAMS dp = { NULL, NULL, 0, 0 };

DISPID dispidNamed = DISPID_PROPERTYPUT;

DISPID putid = DISPID_THIS;

int nArgCount;

//

if(autoType==DISPATCH_METHOD_EX)

{

nArgCount=cArgs+2;

}

else

{

nArgCount=cArgs+1;

}

// Allocate memory for arguments...

VARIANT *pArgs = new VARIANT[nArgCount];

// Extract arguments...

for(int i=nArgCount-2; i>=nArgCount-cArgs-1; i--) {

pArgs[i] = va_arg(marker, VARIANT);

}

if(autoType==DISPATCH_METHOD_EX)

{

pArgs[0].vt=VT_DISPATCH;

pArgs[0].pdispVal=pDisp;

}

/*for(int i=0; i<cArgs; i++) {

pArgs[i] = va_arg(marker, VARIANT);

}*/

// Build DISPPARAMS

dp.cArgs = nArgCount-1;

dp.rgvarg = pArgs;

//

if(autoType==DISPATCH_METHOD_EX)

{

dp.cNamedArgs=1; //should 1

dp.rgdispidNamedArgs=&putid;

}

else

{

// Handle special-case for property-puts!

if(autoType & DISPATCH_PROPERTYPUT)

{

dp.cNamedArgs = 1;

dp.rgdispidNamedArgs = &dispidNamed;

}

}

//

hr=__AutoWrap(autoType,CanIgnore,pvResult,pDisp,ptName,&dp);

//

delete [] pArgs;

return hr;

}

static HRESULT __AutoWrap(int autoType, BOOL CanIgnore, VARIANT *pvResult, IDispatch *pDisp,

LPOLESTR ptName,DISPPARAMS* pDispParams)

{

//

if(!pDisp) {

return E_FAIL;

}

// Variables used...

DISPID dispID;

HRESULT hr;

CComPtr<IDispatchEx> pDispEx;

//pDisp must be IDispatchEx

if(autoType==DISPATCH_METHOD_EX)

{

hr=pDisp->QueryInterface(IID_IDispatchEx,(void**)&pDispEx);

if(FAILED(hr))

return hr;

}

//

if(ptName==NULL || ::wcscmp(ptName,L"")==0)

{

dispID=0;

}

else

{

// Get DISPID for name passed...

if(autoType==DISPATCH_METHOD_EX)

{

CComBSTR bstrName=(LPCTSTR)ptName;

hr=pDispEx->GetDispID(bstrName,fdexNameCaseInsensitive,&dispID);

}

else

{

hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT,

&dispID);

}

if(FAILED(hr))

{

if(CanIgnore)

return S_OK;

else

return hr;

}

}

// Make the call!

CComVariant vResult;

EXCEPINFO exception;

if(autoType==DISPATCH_METHOD_EX)

{

hr=pDispEx->InvokeEx(dispID,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,

pDispParams,&vResult, &exception, NULL);

}

else

{

hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType,

pDispParams, &vResult, &exception, NULL);

}

if(FAILED(hr))

return hr;

if(pvResult!=NULL)

{

vResult.Detach(pvResult);

}

return hr;

}

static bool _StrIsEmpty(LPCTSTR szStr1)

{

return _StrCmp(szStr1,NULL);

}

static bool _StrCmp(LPCTSTR szStr1,LPCTSTR szStr2)

{

if(szStr1==NULL || szStr2==NULL)

{

return (

(szStr1==NULL && (szStr2==NULL || ::wcscmp(szStr2,L"")==0))

||

(szStr2==NULL && (szStr1==NULL || ::wcscmp(szStr1,L"")==0))

);

}

else

{

return ::wcscmp(szStr1,szStr2)==0;

}

}

static bool _StrCmpI(LPCTSTR szStr1,LPCTSTR szStr2)

{

if(szStr1==NULL || szStr2==NULL)

{

return (

(szStr1==NULL && (szStr2==NULL || ::wcscmp(szStr2,L"")==0))

||

(szStr2==NULL && (szStr1==NULL || ::wcscmp(szStr1,L"")==0))

);

}

else

{

return ::_wcsicmp(szStr1,szStr2)==0;

}

}

static bool _BoolCmp(bool b1,bool b2)

{

return (b1 && b2) || (!b1 && !b2);

}

static bool _Bool(VARIANT_BOOL b)

{

return b?true:false;

}

static VARIANT_BOOL _VBool(bool b)

{

return b?VARIANT_TRUE:VARIANT_FALSE;

}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: