本文介绍如何使用 MFC 类和 MFC 类CCmdTarget
CConnectionPoint
实现连接点(以前称为 OLE 连接点)。
过去,组件对象模型(COM)定义了一种通用机制(IUnknown::QueryInterface
*),该机制允许对象在接口中实现和公开功能。 但是,未定义允许对象公开调用特定接口的功能的相应机制。 也就是说,COM 定义了如何处理指向对象的传入指针(指向该对象的接口的指针),但它没有传出接口的显式模型(对象持有到其他对象的接口的指针)。 COM 现在有一个名为连接点的模型,支持此功能。
连接有两个部分:调用接口的对象(称为源)和实现接口的对象(称为接收器)。 连接点是由源公开的接口。 通过公开连接点,源允许接收器建立与自身(源)的连接。 通过连接点机制( IConnectionPoint
接口),指向接收器接口的指针将传递给源对象。 此指针为源提供对一组成员函数的接收器实现的访问权限。 例如,若要触发由接收器实现的事件,源可以调用接收器实现的相应方法。 下图演示了刚才所述的连接点。
实现的连接点
MFC 在 CConnectionPoint 和 CCmdTarget 类中实现此模型。 派生自 CConnectionPoint
实现接口的 IConnectionPoint
类,用于向其他对象公开连接点。 派生自 CCmdTarget
实现接口 IConnectionPointContainer
的类,该接口可以枚举对象的所有可用连接点或查找特定的连接点。
对于在类中实现的每个连接点,必须声明实现连接点的连接部件。 如果实现一个或多个连接点,还必须在类中声明单个连接映射。 连接映射是 ActiveX 控件支持的连接点表。
以下示例演示了一个简单的连接映射和一个连接点。 第一个示例声明连接映射和点;第二个示例实现地图和点。 请注意, CMyClass
必须是 CCmdTarget
-derived 类。 在第一个示例中,代码插入到类声明的节下 protected
:
class CMyClass : public CCmdTarget
{
protected:
// Connection point for ISample interface
BEGIN_CONNECTION_PART(CMyClass, SampleConnPt)
CONNECTION_IID(IID_ISampleSink)
END_CONNECTION_PART(SampleConnPt)
DECLARE_CONNECTION_MAP()
BEGIN_CONNECTION_PART和END_CONNECTION_PART宏声明实现此特定连接点的嵌入式类 XSampleConnPt
(派生自CConnectionPoint
)。 如果要重写任何 CConnectionPoint
成员函数或添加自己的成员函数,请在这两个宏之间声明它们。 例如,宏 CONNECTION_IID
在这两个宏之间放置时会重写 CConnectionPoint::GetIID
成员函数。
第二个示例中,代码插入控件的实现文件(.cpp文件)。 此代码实现连接映射,其中包括连接点: SampleConnPt
BEGIN_CONNECTION_MAP(CMyClass, CCmdTarget)
CONNECTION_PART(CMyClass, IID_ISampleSink, SampleConnPt)
END_CONNECTION_MAP()
如果类有多个连接点,请在BEGIN_CONNECTION_MAP和END_CONNECTION_MAP宏之间插入其他CONNECTION_PART宏。
最后,在类的构造函数中添加对 EnableConnections
调用。 例如:
CMyClass::CMyClass()
{
EnableConnections();
}
插入此代码后, CCmdTarget
派生类会公开接口的连接点 ISampleSink
。 下图说明了此示例。
使用 MFC 实现的连接点
通常,连接点支持“多播”,即能够广播到连接到同一接口的多个接收器。 以下示例片段演示如何通过循环访问连接点上的每个接收器来多播:
void CMyClass::CallSinkFunc()
{
POSITION pos = m_xSampleConnPt.GetStartPosition();
ISampleSink* pSampleSink;
while (pos != NULL)
{
pSampleSink = (ISampleSink*)(m_xSampleConnPt.GetNextConnection(pos));
if (pSampleSink != NULL)
pSampleSink->SinkFunc();
}
}
此示例使用调用CConnectionPoint::GetConnections
检索连接点上的SampleConnPt
当前连接集。 然后循环访问连接并调用 ISampleSink::SinkFunc
每个活动连接。