借助模板类自动实现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分为:迭代器,容器,适配器,算法以及函数对象. --迭代器是一种检查容器内元素并遍 ...
随机推荐
- [LeetCode] 87. Scramble String 搅乱字符串
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- [LeetCode] 5. Longest Palindromic Substring 最长回文子串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- 第09组 Beta冲刺(1/5)
队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 过去两天完成了哪些任务 文字/口头描述 任务分配 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 还剩下哪些任 ...
- multiply two numbers using + opertor
public class Solution { public static void main(String[] args) { , y = ; ; ; i <= y; i++) res = i ...
- oracle--查询速度慢
查询速度慢的原因很多,常见如下几种: 1, 没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2, I/O吞吐量小,形成了瓶颈效应. 3, 没有创建计算列导致查询不优化. 4, ...
- maven setting 配置仓库,pom.xml中repository不起作用
问题描述 最近做java项目,需要使用公司自己搭建的maven仓库,但是有些包公司的仓库中没有,导致下载失败. 项目环境 jdk:1.8 maven:3.5 问题原因分析 maven的setting文 ...
- SQLserver 存储过程游标使用
ALTER PROCEDURE [dbo].[p_DeleteStretchData] ) , ) AS BEGIN ) ) declare @stretch_cursor cursor -- 声明游 ...
- vue 复制文本到剪切板上
1.下载clipboard.js npm install vue-clipboard2 --save 2.引入,可以在mian.js中全局引入也可以在单个vue中引入 import Clipboard ...
- Vue.js 源码分析(十) 基础篇 ref属性详解
ref 被用来给元素或子组件注册引用信息.引用信息将会注册在父组件的 $refs 对象上.如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素:如果用在子组件上,引用就指向组件实例,例如: ...
- 利用开源项目 FFMpegSharp 实现音视频提取、转码、抓图等操作
开源项目地址:https://github.com/vladjerca/FFMpegSharp 首先需要在 web.config 或 app.config 中配置 <appSettings> ...