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

之前在借助模板类自动实现COM连接点接收器(Sink)中对原作者的代码进一步封装,弄清了连接点使用的原理,在看ATL代码的过程中,发现ATL本身就提供了AtlAdvise/AtlUnadvise这样的机制来简化连接点的使用,CComPtrBase中也有Advise这个成员函数,它是对AtlAdvise,进一步封装,因此,对ConnectionHelper的代码可以再简化,简化后Connect()只有十来行了。原作者写的GetConnectPoint函数也用不上了。

?





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

#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 );

    }

};

///////////////////////////////////////////////////////////////////////////////////////////////////////

// ComDllLib::ITestComPtr pCom;

// HRESULT hr = pCom.CreateInstance( L"Test.Com" );

// ConnectionPointHelper<ComDllLib::ITestCom, 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; }

            CComObject<EventProcessor> * pTmp = NULL;

            hr = CComObject<EventProcessor>::CreateInstance( &pTmp );

            if
( FAILED( hr ) ){ break; }

            CComQIPtr<IUnknown, &IID_IUnknown> spSink( pTmp );

            hr = m_spInterface.Advise( spSink, __uuidof(EventInterface), &m_dwCookie );

        } while
( FALSE );

    }

    void
Disconnect()

    {

        HRESULT
hr = E_FAIL;

        do
{

            if
( m_dwCookie == 0 ) { break; }

            AtlUnadvise( m_spInterface, __uuidof(EventInterface), m_dwCookie );

            m_dwCookie = 0;

        } while
( FALSE );

    }

};

#endif // !defined( __sinkimpl_h_INCLUDED__ )

  以上就是全部代码,减少到不到100行。

使用方法:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

{ // .tlh中的接口方式调用

    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 );

        }

    }

}

  

?





1

2

3

4

5

6

7

8

9

10

11

12

{ // IDispatch方式调用

    CComPtr<IDispatch> spDisp;

    HRESULT
hr = spDisp.CoCreateInstance( L"Test.Com"
);

    if
( SUCCEEDED( hr ) )

    {

        CComQIPtr<IUnknown, &IID_IUnknown> spUnknown( spDisp );

        ConnectionPointHelper<ComDllLib::_ITestComEvent, CSink3> cph( spUnknown );

        _variant_t ret;

        _variant_t m = 2, n = 3;

        spDisp.Invoke2( (LPCOLESTR) L"Add", &m, &n, &ret );

    }

}

  

借助模板类自动实现COM连接点接收器(Sink)更新,布布扣,bubuko.com

时间: 2024-10-17 11:54:51

借助模板类自动实现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 1

C++学习34 模板类

C++除了支持模板函数,还支持模板类.模板类的目的同样是将数据类型参数化. 声明模板类的语法为: template<typename 数据类型参数 , typename 数据类型参数 , …> class 类名{ //TODO: }; 模板类和模板函数都是以 template 开头,后跟数据类型参数列表:数据类型参数不能为空,多个参数用逗号隔开. 一但声明了模板类,就可以用数据类型参数来声明类中的成员变量和成员函数.也就是说,原来使用C++内置类型(比如 int.float.char 等)的地

函数模板与模板函数及模板类与模板的特化

函数模板( Function templates) * 模板(Templates)使得我们可以生成通用的函数,这些函数能够接受任意数据类型的参数,可返回任意类型的值,而不需要对所有可能的数据类型进行函数重载.这在一定程度上实现了宏(macro)的作用.它们的原型定义可以是下面两种中的任何一个: template <class identifier> function_declaration; template <typename identifier> function_decla

Spring(二):AOP(面向切面编程),Spring的JDBC模板类

1 AOP概述 1.2 什么是AOP 在软件业,AOP为Aspect Oriented Programmig的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. AOP解决了OOP遇到一些问题,采取横向抽取机制,取代了传统

C++ 模板函数与模板类

一.模板函数 函数模板提供了一类函数的抽象,即代表了一类函数.当函数模板被实例化后,它会生成具体的模板函数.例如下面便是一个函数模板: 当实际调用它时,就会生成具体的模板函数:    模板函数在调用过程中会进行数据类型的自动匹配(在不产生歧义的情况下),但如果需要指定类型的话,可以显示声明,如: 这样,函数模板中的T就会被double所代替. 自动匹配有以下的规则: 1) 函数实参是否满足模板的实参(此时的判断没有数据类型的转换): 2) 若不满足1), 函数实参进行数据转换在进行匹配: 3)

C++提高1 【泛型编程】函数模板 类模板

[本文谢绝转载] [泛型编程] 函数模板 为什么会有函数模板 现象: 函数的业务逻辑一样 函数的参数类型不一样 [最常用]函数模板  显式的调用 [不常用]类型推导 多个参数,参数定义了必须要用 函数模板,实现int类型数组,char字符串排序: 函数模板 与 普通函数的本质区别 函数模板 和 普通函数在一起 的调用型研究: C++是如何支持函数模板机制的? 函数模板机制结论 类模板 类模板的定义 类模板做函数的参数 类模板的派生成普通类 模板类的派生成模板类 复数类,所有函数都写在类的内部,运

【C++】智能指针类和OpenCV的Ptr模板类

智能指针类 引用计数 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象.引用计数为0时,删除对象. 其基本使用规则是: 每次创建类的新对象时,初始化指针并将引用计数置为1.当对象作为另一对象的副本而创建时,复制构造函数复制指针并增加与之相应的引用计数的值.对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数的值(如果引用计数减至0,则删除对

C++_模板类与类型萃取技术

在声明变量,函数,和大多数其他类型实体的时候,C++要求我们使用指定的类型.然而,有许多代码,除了类型不同之外,其余部分看起来都是相同的,比如,下面这个例子: bool IsEqual (int left, int right) {     return left == right; } bool IsEqual (const string& left , const string& right) {     return left == right; } void test() {   

模板函数和模板类的区别

函数模板与类模板的区别 答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化 必 须由程序员在程序中显式地指定. 即函数模板允许隐式调用和显式调用而类模板只能显示调用 这期间有涉及到函数模板与模板函数,类模板与模板类的概念 (类似于类与类对象的区 别) 请看下面例子 注意:模板类的函数声明和实现必须都在头文件中完成,不能像普通类那样声明在.h文件中实现在.cpp文件中,原因可以看链接http://hi.baidu.com/cn_rigel/blog/item/6cf6fc