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;
}
};
__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;
}
};
相关文章推荐
- 在非VS环境下C++ Builder,Delphi,VC,VB等调用C#开发的DLL的完整方法
- 如何调用IDispatch接口的方法和属性
- VS2010开发——vc++项目编写DLL提供vb.net调用
- 用VC开发API形式的DLL给VB调用的范例
- CodeIgniter开发实现支付宝接口调用的方法示例
- Android NDK 开发(三)JNI 调用Java属性和方法
- 2018/01/08JAVA 基础 / 接口与继承:调用父类/子类的类方法、对象方法,访问父类的类属性、对象属性的方式汇总
- Struts的Action接口---(2)Method属性方法调用。
- Android NDK 开发(三)JNI 调用Java属性和方法
- C#调用VC DLL接口函数参数类型转换方法介绍
- 再谈在VB中调用VC++开发的DLL
- VB调用vc写的dll的某个方法时的问题
- C#调用VC DLL接口函数参数类型转换的方法
- 开发中“错误: 意外地调用了方法或属性访问。” 和 第一行错误 的IE 两个问题( JQ 进行转义字符 , 分页JS 调用 时参数问题。)
- C#调用VC DLL接口函数参数类型转换的方法
- C#调用VC DLL接口函数参数类型转换方法介绍
- C#调用VC DLL接口函数参数类型转换方法介绍
- 再谈在VB中调用VC++开发的DLL
- vc调用vb DLL方法
- CodeIgniter开发实现支付宝接口调用的方法示例