奥点云导播台:C++调用ATL事件连接点

来源:百度文库 编辑:中财网 时间:2024/04/28 11:49:11
在调用者工程中,需要增加“接收器”对象,添加一般的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 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 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();
 }