ATL 核心COM继承类之IDispatchImpl及调用
生活随笔
收集整理的這篇文章主要介紹了
ATL 核心COM继承类之IDispatchImpl及调用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?
實現
先看IDispatch接口,如同反射
interface IDispatch : IUnknown { HRESULT GetTypeInfoCount([out] UINT * pctinfo);HRESULT GetTypeInfo([in] UINT iTInfo, [in] LCID lcid, [out] ITypeInfo ** ppTInfo); HRESULT GetIDsOfNames([in] REFIID riid, [in, size_is(cNames)] LPOLESTR * rgszNames,[in] UINT cNames, [in] LCID lcid, [out, size_is(cNames)] DISPID * rgDispId); HRESULT Invoke([in] DISPID dispIdMember, [in] REFIID riid, [in] LCID lcid, [in] WORD wFlags, [in, out] DISPPARAMS * pDispParams, [out] VARIANT * pVarResult, [out] EXCEPINFO * pExcepInfo, [out] UINT * puArgErr); }要實現IDispatch接口的動作是差不多的
class CPenguin :public CComObectRootEx<CComSingleThreadModel>,public IBird,public ISnappyDresser,public IPenguin { public:CPenguin() : m_pTypeInfo(0) {IID* pIID = &IID_IPenguin;GUID* pLIBID = &LIBID_BIRDSERVERLib;WORD wMajor = 1;WORD wMinor = 0;ITypeLib* ptl = 0;HRESULT hr = LoadRegTypeLib(*pLIBID, wMajor, wMinor,0, &ptl);if( SUCCEEDED(hr) ) {hr = ptl->GetTypeInfoOfGuid(*pIID, &m_pTypeInfo);ptl->Release();}}virtual ~Penguin() {if( m_pTypeInfo ) m_pTypeInfo->Release();}BEGIN_COM_MAP(CPenguin)COM_INTERFACE_ENTRY(IBird)COM_INTERFACE_ENTRY(ISnappyDresser)COM_INTERFACE_ENTRY(IDispatch)COM_INTERFACE_ENTRY(IPenguin)END_COM_MAP()// IDispatch methodsSTDMETHODIMP GetTypeInfoCount(UINT *pctinfo) {return (*pctinfo = 1), S_OK;}STDMETHODIMP GetTypeInfo(UINT ctinfo, LCID lcid,ITypeInfo **ppti) {if( ctinfo != 0 ) return (*ppti = 0), DISP_E_BADINDEX;return (*ppti = m_pTypeInfo)->AddRef(), S_OK;}STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames,UINT cNames, LCID lcid, DISPID *rgdispid) {return m_pTypeInfo->GetIDsOfNames(rgszNames, cNames,rgdispid);}STDMETHODIMP Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pdispparams,VARIANT *pvarResult,EXCEPINFO *pexcepinfo,UINT *puArgErr) {return m_pTypeInfo->Invoke(static_cast<IPenguin*>(this),dispidMember, wFlags,pdispparams, pvarResult,pexcepinfo, puArgErr);}// IBird, ISnappyDresser and IPenguin methods... private:ITypeInfo* m_pTypeInfo; };以IDispatchImpl替代
class CPenguin :public CComObjectRootEx<CComMultiThreadModel>,public IBird,public ISnappyDresser,public IDispatchImpl<IPenguin, &IID_IPenguin> { public:BEGIN_COM_MAP(CPenguin)COM_INTERFACE_ENTRY(IBird)COM_INTERFACE_ENTRY(ISnappyDresser)COM_INTERFACE_ENTRY(IDispatch)COM_INTERFACE_ENTRY(IPenguin)END_COM_MAP()// IBird, ISnappyDresser and IPenguin methods... };IDispatchImpl具體實現
template <class T, const IID* piid = &__uuidof(T), const GUID* plibid = &CAtlModule::m_libid, WORD wMajor = 1, WORD wMinor = 0, class tihclass = CComTypeInfoHolder> class ATL_NO_VTABLE IDispatchImpl : public T { public:typedef tihclass _tihclass; // IDispatchSTDMETHOD(GetTypeInfoCount)(_Out_ UINT* pctinfo){if (pctinfo == NULL) return E_POINTER; *pctinfo = 1;return S_OK;}STDMETHOD(GetTypeInfo)(_In_ UINT itinfo, _In_ LCID lcid, _Deref_out_ ITypeInfo** pptinfo){return _tih.GetTypeInfo(itinfo, lcid, pptinfo);}STDMETHOD(GetIDsOfNames)(_In_ REFIID riid, _In_count_(cNames) _Deref_pre_z_ LPOLESTR* rgszNames, _In_ UINT cNames,_In_ LCID lcid, _Out_ DISPID* rgdispid){return _tih.GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);}STDMETHOD(Invoke)(_In_ DISPID dispidMember, _In_ REFIID riid,_In_ LCID lcid, _In_ WORD wFlags, _In_ DISPPARAMS* pdispparams, _Out_opt_ VARIANT* pvarResult,_Out_opt_ EXCEPINFO* pexcepinfo, _Out_opt_ UINT* puArgErr){return _tih.Invoke((IDispatch*)this, dispidMember, riid, lcid,wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);}#ifdef _ATL_DLL_IMPL// Do not cache type info if it is used in the ATL dllIDispatchImpl() : _tih(piid, plibid, wMajor, wMinor){}virtual ~IDispatchImpl(){}protected:_tihclass _tih;HRESULT GetTI(_In_ LCID lcid, _Deref_out_ ITypeInfo** ppInfo){return _tih.GetTI(lcid, ppInfo);}#elseprotected:static _tihclass _tih;static HRESULT GetTI(_In_ LCID lcid, _Deref_out_ ITypeInfo** ppInfo){return _tih.GetTI(lcid, ppInfo);}#endif };調用IDispatch接口
很麻煩的一個過程,如下動態調用Add方法
// component IDL file [object,uuid(2F6C88D7-C2BF-4933-81FA-3FBAFC3FC34B),dual, ] interface ICalc : IDispatch {[id(1)] HRESULT Add([in] DOUBLE Op1,[in] DOUBLE Op2, [out,retval] DOUBLE* Result); };// client.cpp HRESULT CallAdd(IDispatch* pdisp) {// Get the DISPIDLPOLESTR pszMethod = OLESTR("Add");DISPID dispid;hr = pdisp->GetIDsOfNames(IID_NULL,&pszMethod,1,LOCALE_SYSTEM_DEFAULT,&dispid);if (FAILED(hr))return hr;// Set up the parametersDISPPARAMS dispparms;memset(&dispparms, 0, sizeof(DISPPARAMS));dispparms.cArgs = 2;// Parameters are passed right to leftVARIANTARG rgvarg[2];rgvarg[0].vt = VT_R8;rgvarg[0].dblVal = 6;rgvarg[1].vt = VT_R8;rgvarg[1].dblVal = 7;dispparms.rgvarg = &rgvarg[0];// Set up variable to hold method return valueVARIANTARG vaResult;::VariantInit(&vaResult);// Invoke the methodhr = pdisp->Invoke(dispid,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,&dispparms,&vaResult,NULL,NULL);// vaResult now holds sum of 6 and 7 }CComPtr<IDispatch>提供了很多的便利方法
調用如下:
HRESULT TheEasyWay( IDispatch *spCalcDisp ) {CComPtr< IDispatch > spCalcDisp( pCalcDisp );CComVariant varOp1( 6.0 );CComVariant varOp2( 7.0 );CComVariant varResult;HRESULT hr = spCalcDisp.Invoke2( OLESTR( "Add" ),&varOp1, &varOp2, &varResult );// varResult now holds sum of 6 and 7 }轉載于:https://www.cnblogs.com/Clingingboy/archive/2012/09/07/2674935.html
總結
以上是生活随笔為你收集整理的ATL 核心COM继承类之IDispatchImpl及调用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义对话框使用静态Handler传递参
- 下一篇: 电话号码正则表达式