冠冕堂皇

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::

http://msdn.microsoft.com/zh-cn/library/cc451520(v=vs.71).aspx

本文解释如何使用 MFC 类 CCmdTarget 和 CConnectionPoint 来实现连接点(以前称为 OLE 连接点)。

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

一个连接有两个部分:调用接口的对象(称为源)和实现接口的对象(称为接收器)。连接点是源公开的接口。通过公开连接点,源允许接收器建立与源本身的连接。通过连接点机制(IConnectionPoint 接口),指向接收接口的指针传递给源对象。该指针使源有权访问接收器对一组成员函数的实现。例如,为引发接收器实现的事件,源可以调用接收器实现它的适当方法。下图说明刚才描述的连接点。

一个实现的连接点

MFC 在 CConnectionPoint 和 CCmdTarget 类中实现该模型。从 CConnectionPoint 派生的类实现 IConnectionPoint 接口,用于公开到其他对象的连接点。从 CCmdTarget 派生的类实现IConnectionPointContainer 接口,该接口可以枚举某个对象的所有连接点或查找特定的连接点。

对于类中实现的每一个连接点,必须声明实现该连接点的连接部分。如果实现一个或多个连接点,还必须在类中声明单个连接映射。连接映射是由 ActiveX 控件支持的连接点表。

下面的示例说明一个简单的连接映射和一个连接点。第一个示例声明连接映射和点;第二个示例实现此映射和点。请注意,CMyClass 必须是 CCmdTarget 派生的类。在第一个示例中,代码插入到类声明中的 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成员函数或添加您自己的成员函数,请在这两个宏之间声明它们。例如,将 CConnectionPoint::GetIID 成员函数放在这两个宏之间时,CONNECTION_IID 宏重写该成员函数。

在第二个示例中,代码插入到控件的实现文件(.cpp 文件)中。该代码实现连接映射,该连接映射包括连接点 SampleConnPt

 
 
BEGIN_CONNECTION_MAP(CMyClass, CMyBaseClass)
    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()
{
    const CPtrArray* pConnections = m_xSampleConnPt.GetConnections();
    ASSERT(pConnections != NULL);

    int cConnections = pConnections->GetSize();
    ISampleSink* pSampleSink;
    for (int i = 0; i < cConnections; i++)
    {
        pSampleSink = (ISampleSink*)(pConnections->GetAt(i));
        if(pSampleSink != NULL)
            pSampleSink->SinkFunc();
    }
}

该示例通过调用 CConnectionPoint::GetConnections 检索 SampleConnPt 连接点上的当前连接集。然后它循环访问这些连接并在每一个活动连接上调用 ISampleSink::SinkFunc

请参见

MFC COM

posted on 2013-09-10 16:02  冠冕堂皇  阅读(506)  评论(0)    收藏  举报