C++调用ATL事件连接点

14 篇文章 0 订阅
3 篇文章 0 订阅
在调用者工程中,需要增加“接收器”对象,添加一般的C++类对象,从IDispatch 派生,然后完成继承的虚函数,如创建
CSink类,继承自IDispatch ,完成Simple16库中触发事件的接收器。
// 头文件
#pragma once
#include "oaidl.h"
class CSink :
public IDispatch
{
public:
CSink(void);
~CSink(void);
STDMETHOD(QueryInterface)(const struct _GUID &iid,void ** ppv);
ULONG __stdcall AddRef(void);
ULONG __stdcall Release(void);
// IDispatch
STDMETHOD(GetTypeInfoCount)(unsigned int *);
STDMETHOD(GetTypeInfo)(unsigned int,unsigned long,struct ITypeInfo ** );
STDMETHOD(GetIDsOfNames)(const IID &,LPOLESTR *,UINT,LCID,DISPID *);
STDMETHOD(Invoke)(long dispID,const struct _GUID &,unsigned long,unsigned short,struct tagDISPPARAMS * pParams,struct tagVARIANT *,struct tagEXCEPINFO *,unsigned int *);
};
// CPP文件
#include "StdAfx.h"
#include "Sink.h"
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::GetTypeInfoCount(unsigned int *)
{ return E_NOTIMPL; } // 不用实现,反正也不用
STDMETHODIMP CSink::GetTypeInfo(unsigned int,unsigned long,struct ITypeInfo ** )
{ return E_NOTIMPL; } // 不用实现,反正也不用
STDMETHODIMP CSink::GetIDsOfNames(const IID &,LPOLESTR *,UINT,LCID,DISPID *)
{ return E_NOTIMPL; } // 不用实现,反正也不用
STDMETHODIMP CSink::Invoke(
long dispID,
const struct _GUID &,
unsigned long,
unsigned short,
struct tagDISPPARAMS * pParams,
struct tagVARIANT *,
struct tagEXCEPINFO *,
unsigned int *)
{ // 只需要实现这个就足够啦
switch(dispID)
{
case 1: //根据不同的dispID,完成不同的回调函数
// if( !m_pEdit )
// {
// AfxMessageBox( _T("没有调用 SetResultWnd() 设置显示结果的窗口") );
// }
// else
{
CString str;
str.Format( _T("%d"), pParams->rgvarg[0].lVal );
AfxMessageBox(str);
// m_pEdit->SetWindowText( str );
}
break;
case 2:
{
CString str;
str.Format(_T("%d"), pParams->rgvarg[0].lVal);
CString strData;
strData = pParams->rgvarg[1].bstrVal;
}
break;
default:
AfxMessageBox( _T("怎么可能,根本就没有这个号码的函数呀") );
break;
}
return S_OK;
}
假设是基于对话框的MFC应用程序,可以在Dlg中的头文件中做如下定义:
// 接收器对象
CSink m_Sink;
// 组件接口指针
// 采用import DLL方式引入库时由于使用了命名空间,所以在使用库中的接口或对象时需要加入库的名称和::(Simple16Lib::)
// 二采用import tlb no_namespace方式引入库时,不需要使用命名空间
/*Simple16Lib::*/IDispConnectPtr m_spObj;
// 连接点指针
CComQIPtr<IConnectionPoint> m_spCP;
// 连接点的cookie
DWORD m_dwCookie;
// 在CPP文中的可以使用如下代码创建对象
m_dwCookie = 0;
HRESULT hr = m_spObj.CreateInstance(_T("Simple16.DispConnect"));
if (FAILED(hr))
{
AfxMessageBox(_T("没有注册还是没有初始化?"));
CDialog::OnCancel();
}
// 得到连接点容器接口
CComQIPtr<IConnectionPointContainer> spContainer(m_spObj);
if (!spContainer)
{
AfxMessageBox(_T("组件没有提供连接点功能"));
}
// 得到连接点
spContainer->FindConnectionPoint(__uuidof(/*Simple16Lib::*/_IDispConnectEvents), &m_spCP);
if (!m_spCP)
{
AfxMessageBox(_T("没有找到连接点接口"));
}
/* 第二个连接点
spContainer->FindConnectionPoint(__uuidof(/*Simple16Lib::*/_IDispConnectEvents2), &m_spCPTime);
if (!m_spCPTime)
{
AfxMessageBox(_T("没有找到Time连接点接口"));
}
*/
// 连接
hr = m_spCP->Advise(&m_Sink, &m_dwCookie);
if (FAILED(hr))
{
AfxMessageBox(_T("连接失败"));
}
/*
hr = m_spCPTime->Advise(&m_SinkTime, &m_dwCookieTime);
if (FAILED(hr))
{
AfxMessageBox(_T("连接Time失败"));
}
*/
在需要断开连接的地方使用:
if (m_spCP)
{
m_spCP->Unadvise(m_dwCookie);
m_spCP.Release();
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值