连接点

本文介绍如何使用 MFC 类和 MFC 类CCmdTargetCConnectionPoint实现连接点(以前称为 OLE 连接点)。

过去,组件对象模型(COM)定义了一种通用机制(IUnknown::QueryInterface*),该机制允许对象在接口中实现和公开功能。 但是,未定义允许对象公开调用特定接口的功能的相应机制。 也就是说,COM 定义了如何处理指向对象的传入指针(指向该对象的接口的指针),但它没有传出接口的显式模型(对象持有到其他对象的接口的指针)。 COM 现在有一个名为连接点的模型,支持此功能。

连接有两个部分:调用接口的对象(称为源)和实现接口的对象(称为接收器)。 连接点是由源公开的接口。 通过公开连接点,源允许接收器建立与自身(源)的连接。 通过连接点机制( IConnectionPoint 接口),指向接收器接口的指针将传递给源对象。 此指针为源提供对一组成员函数的接收器实现的访问权限。 例如,若要触发由接收器实现的事件,源可以调用接收器实现的相应方法。 下图演示了刚才所述的连接点。

显示已实现的连接点的关系图。
实现的连接点

MFC 在 CConnectionPointCCmdTarget 类中实现此模型。 派生自 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_PARTEND_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 实现的连接点的关系图。
使用 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 每个活动连接。

另请参阅

MFC COM