向CCmdTarget的派生类添加一个接口的实现(2)
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到父类中去找,以此类推。跟消息映射的处理方法是一样的。
- 上一篇:用VC编写具有动态换肤功能的应用程序
- 下一篇:为对话框程序添加工具条和状态栏

