持之以恒
分类: WINDOWS
2009-07-25 14:30:07
消息映射和命令传递
l 消息的分类:
MFC将消息分成三类:
l 命令消息(WM_COMMAND)
UI对象产生的消息都是这种命令消息,可能来自于菜单、加速键、或者是工具栏按钮。凡是派生自CCmdTarget的类都有资格接收命令消息
l 标准消息
除了WM_COMMAND之外,任何以WM_开头的都算是这一类。任何派生自CWnd的类都可以接收此消息
l Control Notification
这种消息由控件产生,为了是向其父窗口通知某种情况
三个宏定义
DECLARE_MESSAGE_MAP()表示该类拥有相应的消息映射表格
BEGIN_MESSAGE_MAP(CLASSNAME,FACLASSNAME)
ONCOMMAND()//指定消息处理函数的名称
END_MESSAGE_MAP
以上的几个宏对应一个庞大的数据结构
DECLARE_MESSAGE_MAP()对应的是
#define
DECLARE_MESSAGE_MAP() \
static
AFX_MESSAGE_ENTRY _messageEntries[];
\
static
AFX_MSGMAP
messageMap;\
virtual AFX_MSGMAP * GetMessageMap() const;
struct
AFX_MSGMAP
{
AFX_MAGMAP
* pBaseMessageMap;
AFX_MSGMAP_ENTRY
* lpEnteries;
}
其中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 o for windows message)
UINT
nLastID; //used for entries specifying a range og control
id’s
UINT
nSig; //signature type (action) or pointer to message
AFX_PMSG
pfn; /runtime to call ( or special value)
}
也就是如下图所示的数据结构
下面就是使用BEGIN.../ON.../END...宏来进行填充相应的数据结构
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));\
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 ) \
};
其中的AfxSig_end定义为:
enum
AfxSig
{
AfxSig_end = 0, //{marks end of message map}
AfxSig_vv,
};
AfxSig_XX用来描述消息处理程序memberFxn的类型(参数和返回值)。
消息的传递:
从AfxWndProc开始
首先来看CWND::WindowProcè调用OnWndMsg(message,wParam,lParam,&lResult),他是用来分配和处理消息的专职的机构
命令消息由OnCommand进行处理
通知消息由OnNotify进行处理
一般的Windows消息,直接在消息的映射表进行上溯,寻找其对应的消息处理程序
BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
如果是WM_COMMAND消息,由虚拟函数OnCommand处理,
}
OnCommand
调用时机:
在OnWndMsg中,如果消息是WM_COMMAND,即命令消息,将调用OnCommand;
在OnCommand中可以对命令处理进行操作。
CWnd实现:
BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam)
{
}
命令消息的接收物类型 |
处理次序 |
Frame窗口 |
View |
Frame本身 |
|
CWinAPP对象 |
|
View |
View本身 |
Document |
|
Document |
Document本身 |
Document Template |
WM_COMMAND的特殊的处理次序