MFC几个主要的机制

来源:互联网 发布:linux取证命令 编辑:程序博客网 时间:2024/05/29 16:43

动态生成机制

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,就有奇特的路线了: