回调方式进行COM组件对外消息传递
情景:被调用者--COM组件;调用者---外部程序
作用:COM组件 到 外部程序 的消息传递
方法:
1.外部程序通过接口类对象,访问接口类的方法。COM对象通过连接点方式,进行消息的反向传递。
2.外部程序通过接口类对象,访问接口类的方法。外部程序对接口类设置回调指针,进行消息的回调。
本文讲第二种方法。
直接上代码:
1.添加新的接口类Iww,作为回调函数类。类似连接点对象的作用。
- interface Iww : IUnknown{
- [helpstring("method Fire_Result")] HRESULT Fire_Result([in] LONG nResult);
- };
2.原有COM对象接口类,添加一个设置回调函数的方法Advise。
- interface Ivv : IUnknown{
- [helpstring("method Advise")] HRESULT Advise(Iww* pCallBack, [out] LONG* pdwCookie);
- [helpstring("method UnAdvise")] HRESULT UnAdvise(LONG dwCookie);
- [helpstring("method Add")] HRESULT Add(LONG n1, LONG n2);
- };
接口类对象:
- class ATL_NO_VTABLE Cvv :
- public CComObjectRootEx<CComSingleThreadModel>,
- public CComCoClass<Cvv, &CLSID_vv>,
- public Ivv
- {
- public:
- Cvv()
- {
- for(int i=0; i<10; i++) // 初始化所有的回调接口为 NULL
- {
- m_pCallBack[i] = NULL;
- }
- }
- DECLARE_REGISTRY_RESOURCEID(IDR_VV)
- BEGIN_COM_MAP(Cvv)
- COM_INTERFACE_ENTRY(Ivv)
- END_COM_MAP()
- DECLARE_PROTECT_FINAL_CONSTRUCT()
- HRESULT FinalConstruct()
- {
- return S_OK;
- }
- void FinalRelease()
- {
- }
- public:
- private:
- Iww * m_pCallBack[10];
- public:
- STDMETHOD(Advise)(Iww* pCallBack, LONG* pdwCookie);
- STDMETHOD(UnAdvise)(LONG dwCookie);
- STDMETHOD(Add)(LONG n1, LONG n2);
- };
- OBJECT_ENTRY_AUTO(__uuidof(vv), Cvv)
- STDMETHODIMP Cvv::Advise(Iww* pCallBack, LONG* pdwCookie)
- {
- // TODO: Add your implementation code here
- if( NULL == pCallBack )
- return E_INVALIDARG;
- for( int i=0; i<10; i++) // 寻找一个保存该接口指针的位置
- {
- if( NULL == m_pCallBack[i] ) // 找到了
- {
- m_pCallBack[i] = pCallBack; // 保存到数组中
- m_pCallBack[i]->AddRef(); // 指针计数器 +1
- *pdwCookie = i + 1; // cookie 就是数组下标
- // +1 的目的是避免使用0,因为0表示无效
- return S_OK;
- }
- }
- return E_OUTOFMEMORY; // 超过10个连接,内存不够用啦
- }
- STDMETHODIMP Cvv::UnAdvise(LONG dwCookie)
- {
- // TODO: Add your implementation code here
- if( dwCookie<1 || dwCookie>10 ) // 这是谁干的呀?乱给参数
- return E_INVALIDARG;
- if( NULL == m_pCallBack[ dwCookie - 1 ] ) // 参数错误,或该接口指针已经无效了
- return E_INVALIDARG;
- m_pCallBack[ dwCookie -1 ]->Release(); // 指针计数器 -1
- m_pCallBack[ dwCookie -1 ] = NULL; // 空出该下标的数组元素
- return S_OK;
- }
- STDMETHODIMP Cvv::Add(LONG n1, LONG n2)
- {
- // TODO: Add your implementation code here
- long nResult = n1 + n2;
- for( int i=0; i<10; i++)
- {
- if( m_pCallBack[i] ) //如果回调接口有效
- m_pCallBack[i]->Fire_Result( nResult ); // 则发出事件/通知
- }
- return S_OK;
- }
3.外部程序,新建一个类继承Iww,并实现raw_Fire_Result方法。
#import "..\ee.tlb" no_namespace
- class CSink :public Iww
- {
- public:
- CSink(void);
- ~CSink(void);
- STDMETHOD(QueryInterface)(const struct _GUID &iid,void ** ppv);
- ULONG __stdcall CSink::AddRef(void);
- ULONG __stdcall CSink::Release(void);
- STDMETHOD(raw_Fire_Result)(long);
- };
- CSink::CSink(void)
- {
- }
- CSink::~CSink(void)
- {
- }
- // STDMETHODIMP 是宏,等价于 long __stdcall
- STDMETHODIMP CSink::QueryInterface(const struct _GUID &iid,void ** ppv)
- {
- *ppv=this;
- return S_OK;
- }
- ULONG __stdcall CSink::AddRef(void)
- { return 1; } // 做个假的就可以,因为反正这个对象在程序结束前是不会退出的
- ULONG __stdcall CSink::Release(void)
- { return 0; } // 做个假的就可以,因为反正这个对象在程序结束前是不会退出的
- STDMETHODIMP CSink::raw_Fire_Result(long nResult)
- {
- // 如果完成了连接,当计算有结果后,该函数会被调用。完成组件通知的功能
- CString str;
- str.Format(_T("%d"),nResult);
- MessageBox(str);
- return S_OK;
- }
4.调用步骤
- CSink m_sink;
- IvvPtr m_spCom;
- DWORD m_dwCookie;
- HRESULT hr = m_spCom.CreateInstance(__uuidof(vv) );
- if( FAILED( hr ) )
- {
- AfxMessageBox( _T("COM对象初始化失败") );
- CDialog::OnCancel();
- }
- hr = m_spCom->Advise( &m_sink, (long *)&m_dwCookie );
- if( SUCCEEDED( hr ) )
- {
- AfxMessageBox( _T("Advise调用成功。已经正确连接") );
- }
- else
- {
- AfxMessageBox( _T("Advise 调用失败") );
- }
- m_spCom->Add(1,5);
回调方式进行COM组件对外消息传递的更多相关文章
- iOS_Swift初识之使用三种回调方式自定义Button
最近在学习Swift ,发现青玉伏案大神早期用OC写的一篇博客--IOS开发之自定义Button(集成三种回调模式) 很适合用来熟悉Swift的回调方式,于是我就用Swift翻版了一下,具体实现原理 ...
- WPF 海康威视网络摄像头回调方式实现断连提示,降低时延
原文:WPF 海康威视网络摄像头回调方式实现断连提示,降低时延 项目需要使用海康威视网络摄像头接入实时视频数据,使用海康威视官方SDK开发,发现没有断连提示的功能,故开发了一个断连提示的功能 在开发过 ...
- 多对多三种创建方式、forms组件、cookies与session
多对多三种创建方式.forms组件.cookies与session 一.多对多三种创建方式 1.全自动 # 优势:不需要你手动创建第三张表 # 不足:由于第三张表不是你手动创建的,也就意味着第三张表字 ...
- Vue3 SFC 和 TSX 方式调用子组件中的函数
在开发中会遇到这样的需求:获取子组件的引用,并调用子组件中定义的方法.如封装了一个表单组件,在父组件中需要调用这个表单组件的引用,并调用这个表单组件的校验表单函数或重置表单函数.要实现这个功能,首先要 ...
- Android简易实战教程--第四十七话《使用OKhttp回调方式获取网络信息》
在之前的小案例中写过一篇使用HttpUrlConnection获取网络数据的例子.在OKhttp盛行的时代,当然要学会怎么使用它,本篇就对其基本使用做一个介绍,然后再使用它的接口回调的方式获取相同的数 ...
- React组件导入的两种方式(动态导入组件的实现)
一. react组件两种导入方式 React组件可以通过两种方式导入另一个组件 import(常用) import component from './component' require const ...
- React-Native子组件修改父组件的几种方式,兄弟组件状态修改(转载)
子组件修改父组件的状态,在开发中非常常见,下面列举了几种方式.DeviceEventEmitter可以跨组件,跨页面进行数据传递,还有一些状态的修改.http://www.jianshu.com/p/ ...
- 使用回调方式写POI导入excel工具类
场景是这样的:为了做一个excel导入的功能,为了尽可能的写一个通用的工具类,将与poi有关的东西都封装起来,以便以其他人员只用关心自己的业务,不用和poi打交道. 写到最后,现在还是会有poi的东西 ...
- C/C++回调方式系列之一 函数指针和函数回调模式
一.函数指针 1. 函数的定义 return_type function_name(parameter list) { function_body } return_type: 返回值,函数一定有返回 ...
随机推荐
- DDD分层架构的三种模式
引言 在讨论DDD分层架构的模式之前,我们先一起回顾一下DDD和分层架构的相关知识. DDD DDD(Domain Driven Design,领域驱动设计)作为一种软件开发方法,它可以帮助我们设计高 ...
- RSA非对称式加解密笔记
1.服务器生成[公钥]和[私钥],成对生成: 2.客户端生成证书信息,使用[公钥]进行加密,前提是有公钥,并生成证书信息: 3.客户端发送自身的计算机名.MAC.用户名.证书内容给服务器: 4.服务器 ...
- Python实现树
树 (tree) 是一种非常高效的非线性存储结构.树,可以很形象的理解,有根,有叶子,对应在数据结构中就是根节点.叶子节点,同一层的叶子叫兄弟节点,邻近不同层的叫父子节点,非常好理解. 注:定义来自百 ...
- 在linux系统下安装两个nginx以及启动、停止、重起
如果没有安装过nginx请看:linux下nginx部署以及配置详解 1.第一个nginx已经安装完成后,现在安装第二个nginx 启动:sudo /usr/sbin/nginx3 重起:sudo / ...
- kubernetes-dashboard登录出现forbidden 403
登录k8s dashboard https://xxxxx:6443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard ...
- netcore 实现跨应用的分布式session
需求场景 网站a,域名为 a.site.com 网站b, 域名为 b.site.com 需要在a.b两个站点之间共享session 解决方案 使用redis作为分布式缓存存储 设置sessionId ...
- 4_PHP流程控制语句_1_条件控制语句
以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. PHP流程控制共有3种类型:条件控制结构.循环结构以及程序跳转和终止语句. 4.1 条件控制语句 4.1.1 if ...
- python写文件无法换行的问题
python写文件无法换行的问题,用'\n' 不行,直接打印的出来了. 网上查了查,都说是用 ‘\r\n’ ,但是这样打出来,不仅换行了,还加了一个空行. windows平台最后结果是 直接 ...
- Matlab工厂模式
工厂模式定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类.工厂模式主要分为简单工厂模式.工厂方法模式以及抽象工厂模式. Obj.m classdef Obj ...
- 【DATAGUARD】物理dg配置客户端无缝切换 (八.2)--Fast-Start Failover 的配置
[DATAGUARD]物理dg配置客户端无缝切换 (八.2)--Fast-Start Failover 的配置 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各 ...