最初的代码源自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__ ) |
使用方法:
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 ); } }; |
借助模板类自动实现COM连接点接收器(Sink),布布扣,bubuko.com
原文:http://www.cnblogs.com/honker/p/3773048.html