连接点实现的一种实用方法






3.77/5 (11投票s)
本文展示了如何实际实现连接点。
引言
我已尽力使本教程非常注重实践,它展示了如何实际实现连接点,而不是专注于理论。在开始任何事情之前,我想衷心感谢 Alex C. Punnen 先生在 Code Project 上发表的文章:COM 连接点。
由于这是我的第一篇文章,我衷心感谢大家的所有建议和评论。
让我们开始
创建一个带有 MFC 支持的基于控制台的应用程序。我们将其命名为 ConClient。
将另一个 ATL 项目添加为当前项目的依赖项。将 ATL 项目命名为 ConServer。
在我们的新 ConServer 中创建一个名为 XMath
的接口。
但这次,请选中 ConnectionPoint 复选框。
然后,构建我们的 ConServer。
您将在您的类视图中看到一个新的接口 _IXMathEvents
。
向我们的接口 XMath
添加一个新方法(请注意此处没有指定返回类型或 [out, retval]
)。
向我们的事件接口(在我们的例子中是 _IXMathEvents
)添加一个新方法。
该方法应该像这样
将该方法添加到事件接口后,请右键单击我们项目的 CoClass,如下图所示
然后,如突出显示的那样,在 Implement Connection Point 对话框中,选择它。您将看到以下屏幕
如图所示,请选中标记为 _IXMathEvents 的框。之后,您将看到一些由向导为我们生成的类,名为 CProxy_IXMathEvents<class T>
。
同样,如果您实现连接点,您将看到一些方法,例如 Fire_ExecutionOver
在 CProxy_IXMathEvents
类中,如果您没有在 CProxy…
类中看到 Fire_ExecutionOver
方法。
双击 CXMath->IXMath->Add
函数的 Add(int n1, int n2)
函数。并编写以下代码行
Fire_ExecutionOver(n1 + n2);
通过在 File 视图中右键单击服务器 DLL 来构建它。
如果您收到一些如下所示的错误
请将 CONNECTION_POINT_ENTRY(IID__IXMathEvents)
行更改为 CONNECTION_POINT_ENTRY(DIID__IXMathEvents)
。
现在将 ConClient 作为活动项目。添加一个从 CCmdTarget
派生的新类 CSink
,并从 Automation 面板中选择 Automation 单选按钮。
将以下行输入到客户端的 StdAfx.h 中
#import "ConServer\Debug\ConServer.DLL" named_guids using namespace CONSERVERLib;
向 CSink
类添加一个成员函数,如 HRESULT Add(int nResult)
。
打开 Sink.CPP 文件 并修改以下行。注释掉 INTERFACE_PART(CSink, IID_ISink, Dispatch)
行并添加 INTERFACE_PART(CSink, DIID__IXMathEvents, Dispatch)
。
BEGIN_INTERFACE_MAP(CSink, CCmdTarget)//DIID__IXMathEvents //INTERFACE_PART(CSink, IID_ISink, Dispatch) INTERFACE_PART(CSink, DIID__IXMathEvents, Dispatch) END_INTERFACE_MAP()
在 DISPATCH MAP 中,添加以下行
DISP_FUNCTION(CSink, "Add", Add, VT_I4, VTS_I4)
更改已在 Sink.CPP 中用红线标记。
将 #include “Sink.h”
添加到主函数的文件中。并将以下代码行写入您的主函数
IXMathPtr ptrMath; CoInitialize(NULL); ptrMath.CreateInstance(__uuidof(XMath)); if(ptrMath) { IConnectionPointContainerPtr ptrConPntCnt = (IDispatch*)ptrMath; IConnectionPointPtr ptrCon; IUnknown* pHandler = NULL; DWORD dwCookie; if(ptrConPntCnt != NULL) { ptrConPntCnt->FindConnectionPoint(DIID__IXMathEvents,&ptrCon); CSink *pSink = new CSink; pHandler = pSink->GetInterface(&IID_IUnknown); ptrCon->Advise(pHandler,&dwCookie); ptrMath->Add(10, 20); ptrCon->Unadvise(dwCookie); ptrCon.Release(); ptrConPntCnt.Release(); delete pSink; } ptrMath.Release(); } CoUninitialize();
成功运行此程序后,您将看到一个消息框,显示的值为 30,如下图所示
在我文章的第二个版本中,我打算使用 eVC++ 4.0 和 VS 7.0 实现连接点。