①动态生成机制
1.
#define DECLARE_DYNAMIC(class_name) \
public: \
static const CRuntimeClass class##class_name; \ 声明对象
virtual CRuntimeClass* GetRuntimeClass() const; \
2.
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, NULL, NULL)
#define IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, pfnNew, class_init) \
AFX_COMDAT const CRuntimeClass class_name::class##class_name = { \
#class_name, sizeof(class class_name), wSchema, pfnNew, \
RUNTIME_CLASS(base_class_name), NULL, class_init }; \//初始化CRuntimeClass对象class##class_name
CRuntimeClass* class_name::GetRuntimeClass() const \
{ return RUNTIME_CLASS(class_name); } \
#define _RUNTIME_CLASS(class_name) ((CRuntimeClass*)(&class_name::class##class_name))
3.下面2个宏是在基类中声明的
#define DECLARE_DYNAMIC(class_name) \
public: \
static const CRuntimeClass class##class_name; \
virtual CRuntimeClass* GetRuntimeClass() const; \
#define IMPLEMENT_DYNAMIC(class_name, base_class_name) \
CObject* PASCAL class_name::CreateObject() \
{ return new class_name;} \
_IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, 0xFFFF, class_name::CreateObject)
② 消息映射机制
首先定义一个数据结构:
struct AFX_MSGMAP
{
AFX_MSGMAP* pBaseMessageMap;
AFX_MSGMAP_ENTRY* lpEntries;
};
其中的AFX_MSGMAP_ENTRY 又是另一个数据结构:
struct AFX_MSGMAP_ENTRY // MFC 4.0 format
{
UINT nMessage; // windows message
UINT nCode; // control code or WM_NOTIFY code
UINT nID; // control ID (or 0 for windows messages)
UINT nLastID; // used for entries specifying a range of control id's
UINT nSig; // signature type (action) or pointer to message #
AFX_PMSG pfn; // routine to call (or special value)
};
其中的 AFX_PMSG 定义为函数指针:
typedef void (CCmdTarget::*AFX_PMSG)(void);
然后我们定义一个宏:
#define DECLARE_MESSAGE_MAP() \
static AFX_MSGMAP_ENTRY _messageEntries[]; \
static AFX_MSGMAP messageMap; \它里面的lpEntries就指向_messageEntries,从下面的定义中就可以看出来
virtual AFX_MSGMAP* GetMessageMap() const;
于是,DECLARE_MESSAGE_MAP 就相当于声明了这样一个数据结构:
这个数据结构的内容填塞工作由三个宏完成:
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
AFX_MSGMAP* theClass::GetMessageMap() const \
{ return &theClass::messageMap; } \
AFX_MSGMAP theClass::messageMap = \
{ &(baseClass::messageMap), \
(AFX_MSGMAP_ENTRY*) &(theClass::_messageEntries) }; \ 这对应的值是messageMap的lpEntries
AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \
{
#define ON_COMMAND(id, memberFxn) \
{WM_COMMAND,0,(WORD)id,(WORD)id,AfxSig_vv,(AFX_PMSG)memberFxn},
#define END_MESSAGE_MAP() \
{ 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
};
消息的终极镖靶 CCmdTarget 的映射表内容:
AFX_MSGMAP CCmdTarget::messageMap =
{
NULL,
&CCmdTarget::_messageEntries[0]
};
AFX_MSGMAP_ENTRY CCmdTarget::_messageEntries[] =
{
{ 0, 0, CCmdTargetid, 0, AfxSig_end, 0 }
};
消息的流向
如果是一般的Windows消息(WM_xxx),一定是由派生类流向基类,没有旁流的可能。
如果是命令消息WM_COMMAND,就有奇特的路线了: