首页 > 代码库 > 借助模板类自动实现COM连接点接收器(Sink)
借助模板类自动实现COM连接点接收器(Sink)
最初的代码源自free2000fly的一个标准的 COM 连接点接收器(Sink)的实现, 使用相当简单!!!,作者封装了不少工作,但调用时的代码还可以再封装一下,最后只要拷贝并修改Sink实现类的Invoke就好了。
以下是这个代码的头文件 "sinkimpl.h",比free2000fly的"sinkimpl.h"多了一个模板类ConnectionPointerHelper<>
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | #if !defined( __sinkimpl_h_INCLUDED__ ) #define __sinkimpl_h_INCLUDED__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 template < typename T, typename EventInterface, const GUID * evtLibID = NULL > class ATL_NO_VTABLE CSinkImpT : public CComObjectRootEx<CComSingleThreadModel> , public CComCoClass<CSinkImpT<T, EventInterface, evtLibID>, &__uuidof(T)> , public IDispatchImpl < EventInterface, &__uuidof(EventInterface), evtLibID > { public : CSinkImpT() {} virtual ~CSinkImpT() {} typedef IDispatchImpl<EventInterface, &__uuidof(EventInterface), evtLibID> _parentClass; typedef CSinkImpT<T, EventInterface, evtLibID> _thisClass; STDMETHOD( Invoke )(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT * puArgErr) { T * pThis = static_cast <T *>( this ); return pThis->DoInvoke( dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); } DECLARE_NO_REGISTRY() DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP( _thisClass ) COM_INTERFACE_ENTRY( IDispatch ) COM_INTERFACE_ENTRY( EventInterface ) END_COM_MAP(); STDMETHOD( DoInvoke )(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT * puArgErr) { return _parentClass::Invoke( dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); } }; inline HRESULT WINAPI GetConnectPoint( IUnknown * pItf, const IID & rSinkIID, IConnectionPoint ** ppCP ) { HRESULT hr = E_FAIL; do { if ( pItf == NULL || ppCP == NULL ) { break ; } CComQIPtr<IConnectionPointContainer> spContainer; hr = pItf->QueryInterface( &spContainer ); if ( FAILED( hr ) ) { break ; } hr = spContainer->FindConnectionPoint( rSinkIID, ppCP ); } while ( FALSE ); return hr; } /////////////////////////////////////////////////////////////////////////////////////////////////////// // 使用方法: // ComDllLib::ITestComPtr pCom; // HRESULT hr = pCom.CreateInstance( L"Test.Com" ); // ConnectionPointHelper<ComDllLib::_ITestComEvent, CSink3> cph( pCom ); // template < typename EventInterface, typename EventProcessor> class ConnectionPointHelper { CComPtr<IUnknown> m_spInterface; DWORD m_dwCookie; public : ConnectionPointHelper( IUnknown* pInterface ) : m_spInterface( pInterface ), m_dwCookie( 0 ) { Connect(); } ~ConnectionPointHelper() { Disconnect(); } protected : void Connect() { HRESULT hr = E_FAIL; do { if ( m_spInterface == NULL || m_dwCookie != 0 ) { break ; } CComQIPtr<IConnectionPoint> spCP; hr = GetConnectPoint( m_spInterface, __uuidof(EventInterface), &spCP ); if ( FAILED( hr ) ){ break ; } CComQIPtr<IDispatch> spSink; { CComObject<EventProcessor> * pTmp = NULL; hr = CComObject<EventProcessor>::CreateInstance( &pTmp ); if ( FAILED( hr ) ){ break ; } pTmp->AddRef(); hr = pTmp->QueryInterface( &spSink ); pTmp->Release(); if ( FAILED( hr ) ){ break ; } } spCP->Advise( spSink, &m_dwCookie ); } while ( FALSE ); } void Disconnect() { HRESULT hr = E_FAIL; do { if ( m_dwCookie == 0 ) { break ; } CComQIPtr<IConnectionPoint> spCP; hr = GetConnectPoint( m_spInterface, __uuidof(EventInterface), &spCP ); if ( FAILED( hr ) ){ break ; } hr = spCP->Unadvise( m_dwCookie ); m_dwCookie = 0; } while ( FALSE ); } }; #endif // !defined( __sinkimpl_h_INCLUDED__ ) |
使用方法:
+ View Code?
1 2 3 4 5 6 7 8 9 10 11 12 13 | UIAddChildWindowContainer( m_hWnd ); ComDllLib::ITestComPtr pCom; CComPtr<IUnknown> pUnknown; HRESULT hr = pCom.CreateInstance( L "Test.Com" ); if (SUCCEEDED(hr)) { hr = pCom->QueryInterface( IID_IUnknown, reinterpret_cast < void **>(&pUnknown) ); if ( SUCCEEDED( hr ) ) { ConnectionPointHelper<ComDllLib::_ITestComEvent, CSink3> cph( pUnknown ); LONG c = pCom->Add( 1, 5 ); } } |
CSink3的实现(与free2000fly写的一样):
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | // 要响应连接点事件,只需要重写此类 // class DECLSPEC_UUID( "492194D9-7BEE-422D-AE7C-C43A809F20EC" ) CSink3; class ATL_NO_VTABLE CSink3 : public CSinkImpT < CSink3, ComDllLib::_ITestComEvent > { public : CSink3( void ) { } virtual ~CSink3( void ) {} typedef CSinkImpT<CSink3, ComDllLib::_ITestComEvent> _parentClass; STDMETHOD( DoInvoke )(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT * puArgErr) { // 3. the dispidMember must referenced from .thl file, and you can have a look using oleview.exe switch ( dispidMember ) { case 1: { CComVariant result( *pvarResult ); if ( SUCCEEDED( result.ChangeType( VT_BSTR ) ) ) ::MessageBoxW( ::GetActiveWindow(), result.bstrVal, L "Sink Message" , MB_OK ); return S_OK; } default : break ; } return _parentClass::DoInvoke( dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr ); } }; |
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。