龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > VC开发 >

向CCmdTarget的派生类添加一个接口的实现(2)

时间:2009-12-30 15:42来源:未知 作者:admin 点击:
分享到:
struct AFX_INTERFACEMAP { const AFX_INTERFACEMAP* (PASCAL* pfnGetBaseMap)(); // NULL is root class const AFX_INTERFACEMAP_ENTRY* pEntry; // map for this class }; #define DECLARE_INTERFACE_MAP() privat

struct AFX_INTERFACEMAP
{
    const AFX_INTERFACEMAP* (PASCAL* pfnGetBaseMap)(); // NULL is root class
    const AFX_INTERFACEMAP_ENTRY* pEntry; // map for this class
};

#define DECLARE_INTERFACE_MAP()
private:
    static const AFX_INTERFACEMAP_ENTRY _interfaceEntries[];
protected:
    static AFX_DATA const AFX_INTERFACEMAP interfaceMap;
    static const AFX_INTERFACEMAP* PASCAL _GetBaseInterfaceMap();
    virtual const AFX_INTERFACEMAP* GetInterfaceMap() const;
 

(2)BEGIN_INTERFACE_PART/END_INTERFACE_PART

#define BEGIN_INTERFACE_PART(localClass, baseClass) // 定义了一个嵌套类
    class X##localClass : public baseClass
    {
    public:
        STDMETHOD_(ULONG, AddRef)();
        STDMETHOD_(ULONG, Release)();
        STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj);

#define END_INTERFACE_PART(localClass)
    } m_x##localClass;
    friend class X##localClass;
 

(3)BEGIN_INTERFACE_MAP/INTERFACE_PART/END_INTERFACE_MAP

#define offsetof(s,m) (size_t)&(((s *)0)->m)

#define BEGIN_INTERFACE_MAP(theClass, theBase)
    const AFX_INTERFACEMAP* PASCAL theClass::_GetBaseInterfaceMap()
        { return &theBase::interfaceMap; }
    const AFX_INTERFACEMAP* theClass::GetInterfaceMap() const
        { return &theClass::interfaceMap; }
    AFX_COMDAT const AFX_DATADEF AFX_INTERFACEMAP theClass::interfaceMap =
        { &theClass::_GetBaseInterfaceMap, &theClass::_interfaceEntries[0], };
    AFX_COMDAT const AFX_DATADEF AFX_INTERFACEMAP_ENTRY theClass::_interfaceEntries[] =
    {

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

#define END_INTERFACE_MAP()
        { NULL, (size_t)-1 }
    };

(4)METHOD_PROLOGUE_EX

#define METHOD_PROLOGUE_EX(theClass, localClass)
    METHOD_PROLOGUE(theClass, localClass)

#define METHOD_PROLOGUE(theClass, localClass)
    theClass* pThis =
        ((theClass*)((BYTE*)this - offsetof(theClass, m_x##localClass)));
    AFX_MANAGE_STATE(pThis->m_pModuleState)
    pThis; // avoid warning from compiler

  METHOD_PROLOGUE最大的作用就是得到pThis指针。该宏用在嵌套类的成员函数中,pThis是其父类的指针,这里也即是CSampleView的this指针。

  这些宏与MFC中的消息映射宏非常的相似,在侯捷的《深入浅出MFC》中对消息映射宏有非常详细的讲述。我也无意画蛇添足。它的基本思想就是把各个嵌套类的对象(即m_x开头的变量)放到一个数组里,这样在QueryInterface时就可以得到这些接口的指针了,所谓的接口指针也就是这些嵌套类对象的地址。

  CCmdTarget包含了三个函数:ExternalAddRef、ExternalRelease、ExternalQueryInterface。这样我们就不用自己实现IUnknown接口了,只要简单地调用父类的函数就可以了,这实在是很方便。ExternalQueryInterface的执行过程就是先在子类中找要查询的接口,如果找到了就返回其接口指针。如果找不到就通过GetBaseInterfaceMap到父类中去找,以此类推。跟消息映射的处理方法是一样的。

精彩图集

赞助商链接