借助模板类自动实现COM连接点接收器(Sink)更新
之前在借助模板类自动实现COM连接点接收器(Sink)中对原作者的代码进一步封装,弄清了连接点使用的原理,在看ATL代码的过程中,发现ATL本身就提供了AtlAdvise/AtlUnadvise这样的机制来简化连接点的使用,CComPtrBase中也有Advise这个成员函数,它是对AtlAdvise,进一步封装,因此,对ConnectionHelper的代码可以再简化,简化后Connect()只有十来行了。原作者写的GetConnectPoint函数也用不上了。
#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行。
使用方法:
{ // .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 );
}
}
}
{ // 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)更新的更多相关文章
- 借助模板类自动实现COM连接点接收器(Sink)
本文的更新:借助模板类自动实现COM连接点接收器(Sink)更新 (2014-06-09 17:09) 最初的代码源自free2000fly的一个标准的 COM 连接点接收器(Sink)的实现, 使用 ...
- C++学习34 模板类
C++除了支持模板函数,还支持模板类.模板类的目的同样是将数据类型参数化. 声明模板类的语法为: template<typename 数据类型参数 , typename 数据类型参数 , …&g ...
- C++17尝鲜:类模板中的模板参数自动推导
模板参数自动推导 在C++17之前,类模板构造器的模板参数是不能像函数模板的模板参数那样被自动推导的,比如我们无法写 std::pair a{1, "a"s}; // C++17 ...
- c# 利用t4模板,自动生成Model类
我们在用ORM(比如dapper)的时候,很多时候都需要自己写Model层(当然也有很多orm框架自带了这种功能,比如ef),特别是表里字段比较多的时候,一个Model要写半天,而且Model如果用于 ...
- QCache 缓存(模板类,类似于map,逻辑意义上的缓存,方便管理,和CPU缓存无关。自动获得被插入对象的所有权,超过一定数量就会抛弃某些值)
在软件开发中,我们经常需要在内存中存储一些临时数据用于后续相关计算.我们一般把这些数据存储到某个数组里,或者STL中的某个合适的容器中.其实,在Qt中直接为我们提供了一个QCache类专用于这种需求. ...
- c++模板类
c++模板类 理解编译器的编译模板过程 如何组织编写模板程序 前言常遇到询问使用模板到底是否容易的问题,我的回答是:“模板的使用是容易的,但组织编写却不容易”.看看我们几乎每天都能遇到的模板类吧,如S ...
- C++ 模板函数与模板类
一.模板函数 函数模板提供了一类函数的抽象,即代表了一类函数.当函数模板被实例化后,它会生成具体的模板函数.例如下面便是一个函数模板:
- 开涛spring3(7.2) - 对JDBC的支持 之 7.2 JDBC模板类
7.2 JDBC模板类 7.2.1 概述 Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDB ...
- STL标准模板类
STL,中文名标准模板库,是一套C++的标准模板类(是类!),包含一些模板类和函数,提供常用的算法和数据结构. STL分为:迭代器,容器,适配器,算法以及函数对象. --迭代器是一种检查容器内元素并遍 ...
随机推荐
- SCITE设置修改说明
SCITE设置修改说明选项→打开全局设置文件:1.启动时最大化:position.width=-1position.height=-12.用于中文系统,要修改语言.code.page=936outpu ...
- [LeetCode] 189. Rotate Array 旋转数组
Given an array, rotate the array to the right by k steps, where k is non-negative. Example 1: Input: ...
- Ensight——Fluent重叠网格解决方案【翻译】
原文链接:https://support.ceisoftware.com/hc/en-us/articles/360000664191-Overset-Grid-Solutions-from-Flue ...
- 推荐一款语音直播连麦App YAMI
推荐一款语音直播连麦App YAMI 1 介绍 功能描述:[语音直播]:海量超有才主播,游戏送礼抢红包,嗨玩不停:[多人聊天室]:连麦交友处CP,主持人带你玩游戏,边聊边玩:[语音交友]:海量声优专属 ...
- Windwos Server 2016 远程桌面授权
https://blog.csdn.net/hanzheng260561728/article/details/80443135 第二步激活客户的的时候,注意事项
- Qt 操作SQLite数据库
项目中通常需要采用各种数据库(如 Qracle.SQL Server.MySQL等)来实现对数据的存储.查询等功能.下面讲解如何在 Qt 中操作 SQlite 数据库. 一.SQLite 介绍 Sql ...
- 记录webservice
公司的一个老项目,定义了接口,供其他应用访问.定义的方式就是webservice. 我这边的环境是springboot. 首先引入依赖jar 声明一个服务端. @WebSerevice注解中name则 ...
- golang net之http server
golang 版本:1.12.9 简单的HTTP服务器代码: package main import ( "net/http" ) type TestHandler struct ...
- 前端开发vscode必备插件
VSCode 插件 Atom one Dark Theme Atom Dark主题 Auto Close Tag 自动关闭标签 Auto Rename Tag 自动重命名标签 Beautify 格式化 ...
- fiverr无法注册的解决办法,fiverr注册教程
转载 https://www.wok99.com/450.html