码迷,mamicode.com
首页 > 其他好文 > 详细

借助模板类自动实现COM连接点接收器(Sink)

时间:2014-06-11 09:38:08      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:style   class   blog   code   http   color   

最初的代码源自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__ )

  

使用方法:

  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

借助模板类自动实现COM连接点接收器(Sink)

标签:style   class   blog   code   http   color   

原文地址:http://www.cnblogs.com/honker/p/3773048.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!