3.MFC消息映射机制
类内必须添加声明宏
DECLARE_MESSAGE_MAP()
类外必须添加实现宏
BEGIN_MESSAGE_MAP(theClass,baseClass)
END_MESSAGE_MAP()
具体实现:
class CMyFrameWnd : public CFrameWnd {
DECLARE_MESSAGE_MAP();
public:
LRESULT MyOnCreate(WPARAM wParam,LPARAM lParam);
};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
ON_MESSAGE(WM_CREATE, MyOnCreate)
END_MESSAGE_MAP()
LRESULT CMyFrameWnd::MyOnCreate(WPARAM wParam, LPARAM lParam) {
AfxMessageBox(TEXT("WM_Create"));
return 0;
}
3.1宏展开
#define DECLARE_MESSAGE_MAP() \
protected: \
static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
const AFX_MSGMAP* GetMessageMap() const override; \
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
PTM_WARNING_DISABLE \
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
__pragma(warning(push)) \
__pragma(warning(disable: 4640)) /* message maps can only be called by single threaded message pump */ \
static const AFX_MSGMAP_ENTRY _messageEntries[] = \
{
#define ON_MESSAGE(message, memberFxn) \
{ message, 0, 0, 0, AfxSig_lwl, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
(memberFxn)) },
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
__pragma(warning(pop)) \
static const AFX_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \
} \
PTM_WARNING_RESTORE
简单整理一下
protected:
static const AFX_MSGMAP* PASCAL GetThisMessageMap();
const AFX_MSGMAP* GetMessageMap() const override;
const AFX_MSGMAP* CMyFrameWnd::GetMessageMap() const {
return GetThisMessageMap();
}
const AFX_MSGMAP* PASCAL CMyFrameWnd::GetThisMessageMap()
{
static const AFX_MSGMAP_ENTRY _messageEntries[] =
{
{WM_CREATE, 0, 0, 0, AfxSig_lwl, (AFX_PMSG)(AFX_PMSGW)
(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) >(&MyOnCreate))},
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0}
};
static const AFX_MSGMAP messageMap = { &CFrameWnd::GetThisMessageMap, &_messageEntries[0] };
return &messageMap;
}
找到其中两个结构体
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; //消息标志
UINT nCode; //控制代码或WM_NOTIFY通知码
UINT nID; //控件ID,如果是窗口消息,其值为0
UINT nLastID; //一定范围命令的最后一个命令或控件ID,用于支持组消息映射
UINT_PTR nSig; //消息处理成员函数的签名代码
AFX_PMSG pfn; //消息处理函数
};
static const AFX_MSGMAP messageMap = {
&CFrameWnd::GetThisMessageMap,
&_messageEntries[0]
};
GetThisMessageMap() 静态函数
作用 : 定义静态变量和静态数组,并返回本类静态变量地址( 获取链表头)
messageEntries静态数组
作用: 数组每个元素,保存的为 消息ID 和 处理消息的函数名( 地址 )
messageMap静态变量
作用: 第一个成员,保存父类宏展开的静态变量地址( 负责连接链表 第二个成员,保存本类的静态数组首地址)
GetMessageMap()虚函数
作用 : 返回本类静态变量地址( 获取链表头)
3.2 消息映射宏
消息映射声明和分界宏
名称 | 说明 |
---|---|
DECLARE_MESSAGE_MAP | 声明将在类中使用消息映射来将消息映射到函数(必须在类声明中使用)。 |
BEGIN_MESSAGE_MAP | 开始消息映射的定义(必须在类实现中使用)。 |
BEGIN_TEMPLATE_MESSAGE_MAP | 开始在包含单个模板参数的类类型上定义消息映射。 |
END_MESSAGE_MAP | 结束消息映射的定义(必须在类实现中使用)。 |
消息映射宏
名称 | 说明 |
---|---|
ON_COMMAND | 指示哪个函数将处理指定的命令消息。 |
ON_COMMAND_EX | 指示哪个函数将处理指定的命令消息。 |
ON_CONTROL | 指示哪个函数将处理指定的控件通知消息。 |
ON_MESSAGE | 指示哪个函数将处理用户定义的消息。 |
ON_OLECMD | 指示哪个函数将处理 DocObject 或其容器中的菜单命令。 |
ON_REGISTERED_MESSAGE | 指示哪个函数将处理已注册的用户定义消息。 |
ON_REGISTERED_THREAD_MESSAGE | 指示哪个函数将在您具有 CWinThread 类时处理已注册的用户定义消息。 |
ON_THREAD_MESSAGE | 指示哪个函数将在您具有 CWinThread 类时处理用户定义的消息。 |
ON_UPDATE_COMMAND_UI | 指示哪个函数将处理指定的用户界面更新命令消息。 |
消息映射范围宏
名称 | 说明 |
---|---|
ON_COMMAND_RANGE | 指示哪个函数将处理在宏的前两个参数中指定的命令 ID 的范围。 |
ON_UPDATE_COMMAND_UI_RANGE | 指示哪个更新处理程序将处理在宏的前两个参数中指定的命令 ID 的范围。 |
ON_CONTROL_RANGE | 指示哪个函数将处理来自在宏的第二个和第三个参数中指定的控件 ID 的范围的通知。 第一个参数是控件通知消息,如 BN_CLICKED 。 |
3.3 WM_ 消息的处理程序
以下主题与映射条目相对应。
主题 | 映射条目 |
---|---|
A - C | ON_WM_ACTIVATE 至 ON_WM_CTLCOLOR |
D - E | ON_WM_DEADCHAR 至 ON_WM_ERASEBKGND |
F - K | ON_WM_FONTCHANGE 至 ON_WM_KILLFOCUS |
L - M | ON_WM_LBUTTONDBLCLK 至 ON_WM_MOVING |
N - O | ON_WM_NCACTIVATE 至 ON_WM_NCRBUTTONUP |
P - R | ON_WM_PAINT 至 ON_WM_RENDERFORMAT |
S | ON_WM_SETCURSOR 至 ON_WM_SYSKEYUP |
T - Z | ON_WM_TIMECHANGE 至 ON_WM_WININICHANGE |
3.4 用户定义的处理程序
下面的映射条目对应于函数原型。
映射条目 | 函数原型 |
---|---|
ON_MESSAGE( , ) | afx_msg LRESULT memberFxn( WPARAM, LPARAM ); |
ON_REGISTERED_MESSAGE( , ) | afx_msg LRESULT memberFxn( WPARAM, LPARAM ); |
ON_THREAD_MESSAGE( , ) | afx_msg void memberFxn( WPARAM, LPARAM ); |
ON_REGISTERED_THREAD_MESSAGE( , ) | afx_msg void memberFxn( WPARAM, LPARAM ); |