《com原理与应用读书笔记》---可连接对象

本文详细解析了MFC框架中实现COM连接点的具体方法,包括CConnectionPoint类的内部结构,连接点对象的声明与定义,以及如何通过宏定义完成连接点与接口的映射。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可连接对象这章,作者在写MFC对连接和时间的支持这章有点乱。我稍微整理了下。

一、mfc实现连接点类IConnectionPoint接口

        mfc用CConnectionPoint类继承了CCmdTarget类,并用一个数组枚举器管理连接。

class CConnectionPoint::CCmdTarget

{

    public: CConnectionPoint();

    

    POSITION GetStartPosition() const;

    LPUNKNOWN GetNextConnection(POSITION &pos) const;

    const CPtrArray * GetConnections()//obsolete  

      。。

    protected:

    ...

    CPtrArray * m_pConnections;//书上说的数组枚举器应该就是它了吧

    //Interface maps

    public:

   //这里才是CConnectionPoint类定义了ConnPt嵌套类,并且实现IConnectionPoint接口

    BEGIN_INTERFACE_PART(ConnPt, IConnectionPoint)

        INIT_INTERFACE_PART(CConnectionPoint,ConnPt)

        STDMETHOD(GetConnectionInterface)(IID* pIID);

        STDMETHOD(GetConnectionPointContainer)(...);

        STDMETHOD(Advise)(...);

        STDMETHOD(Unadvise)();

        STDMETHOD(EnumConnections)();

    END_INTERFACE_PART(ConnPt)

}

二、CCmdTarget提供的支持连接点对象的一组宏

1、首先在源对象定义中使用DECLARE_CONNECTION_MAP宏,定义一张连接(点)映射表以及有关表的操作函数。其宏内容如下:

#ifdef _AFXDLL
#define DECLARE_CONNECTION_MAP() /
private: /
 static const AFX_CONNECTIONMAP_ENTRY _connectionEntries[]; /
protected: /
 static AFX_DATA const AFX_CONNECTIONMAP connectionMap; /
 static const AFX_CONNECTIONMAP* PASCAL _GetBaseConnectionMap(); /
 virtual const AFX_CONNECTIONMAP* GetConnectionMap() const; /

#else
#define DECLARE_CONNECTION_MAP() /
private: /
 static const AFX_CONNECTIONMAP_ENTRY _connectionEntries[]; /
protected: /
 static AFX_DATA const AFX_CONNECTIONMAP connectionMap; /
 virtual const AFX_CONNECTIONMAP* GetConnectionMap() const; /

#endif

#endif //!_AFX_NO_OLE_SUPPORT

 

2、然后用

BEGIN_CONNECTION_PART CMySourceObjMyEventSet

       //可以用下面的类定义重载更多的虚函数

       virtual void OnAdviseBool bAdvise;

       virtual REFIID GetIID();// 有时也用CONNECTION_IIDIID_IMyEventSet

       virtual LPUNKNOWN    QuerrySinkInterfaceLPUNKNOWN pUkSink;

END_CONNECTION_PART (MyEventSet)

来声明及定义连接点对象MyEventSet。该宏的定义如下。

#define BEGIN_CONNECTION_PART(theClass, localClass) /

       class X##localClass : public CConnectionPoint /

       { /

       public: /

              X##localClass() /

                     { m_nOffset = offsetof(theClass, m_x##localClass); }

 

#define CONNECTION_IID(iid) /

              REFIID GetIID() { return iid; }

 

#define END_CONNECTION_PART (localClass) /

       } m_x##localClass; /

       friend class X##localClass;

显然,这里定义了一个嵌套类XMyEventSet,并且它继承了CConnectionPoint类,实现了对IConnectionPoint接口的继承。最后END_CONNECTION_PART定义了一个内嵌的类成员m_xMyEventSet,在激发事件函数中要用到此成员。

 

3、DECLARE_CONNECTION_MAP建立一张连接映射表,源对象CMySourceObj

BEGIN_CONNECTION_MAP (CMySourceObj, CCmdTarget)

       CONNECTION_PART ( CMySourceObj IID_IMyEventSetMyEventSet)

END_CONNECTION_MAP ()

实现连接映射表。M_xMyEventSet

#ifdef _AFXDLL

#define BEGIN_CONNECTION_MAP (theClass, theBase) /

       const AFX_CONNECTIONMAP* PASCAL theClass::_GetBaseConnectionMap() /

              { return &theBase::connectionMap; } /

       const AFX_CONNECTIONMAP* theClass::GetConnectionMap() const /

              { return &theClass::connectionMap; } /

       AFX_COMDAT const AFX_DATADEF AFX_CONNECTIONMAP theClass::connectionMap = /

              { &theClass::_GetBaseConnectionMap, &theClass::_connectionEntries[0], }; /

       AFX_COMDAT const AFX_DATADEF AFX_CONNECTIONMAP_ENTRY theClass::_connectionEntries[] = /

       { /

 

#else

#define BEGIN_CONNECTION_MAP(theClass, theBase) /

       const AFX_CONNECTIONMAP* theClass::GetConnectionMap() const /

              { return &theClass::connectionMap; } /

       AFX_COMDAT const AFX_DATADEF AFX_CONNECTIONMAP theClass::connectionMap = /

              { &(theBase::connectionMap), &theClass::_connectionEntries[0], }; /

       AFX_COMDAT const AFX_DATADEF AFX_CONNECTIONMAP_ENTRY theClass::_connectionEntries[] = /

       { /

 

#endif

 

#define CONNECTION_PART (theClass, iid, localClass) /

              { &iid, offsetof(theClass, m_x##localClass) }, /

 

#define END_CONNECTION_MAP() /

              { NULL, (size_t)-1 } /

       }; /

4、接口映射表

BEGIN_INTERFACE_MAP (CSourceObj, CCmdTarget)

       INTERFACE_PART(CSourceObjIID_ISourceObjDispatch)

//上一句其实就是定义了AFX_INTERFACEMAP_ENTRY的一个值,iidoffset

    // INTERFACE_PART(theClass, iid, localClass)localClass用来计算接口的偏移量

END_INTERFACE_MAP ()

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

METHOD_PROLOGUE_EX (theClass, localClass)

这个宏就是为了获得外围类的指针。

METHOD_PROLOGUE_EX(CDictionary,  Dictionary)这句话之外,还需要知道CDictionaryDictionary类的定义。这个方法的主要用法就是知道嵌套类的指针,怎样获取外围类的指针。找到偏移,减去即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值