在调用者工程中,需要增加“接收器”对象,添加一般的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(); } |
|