Message Mapping and Command Routing
1、MFC把消息三大类:
1)命令消息(WM_COMMAND):凡由UI 对象产生的消息都是这种命令消息,可能来自菜单或加速键或工具栏。SDK程序主要靠消息的wParam 辨识之,MFC程序则主要靠菜单项目的识别码(menu ID)辨识之,两者其实是相同的。
凡衍生自CCmdTarget 的类别,皆有资格接收改类型消息。几乎构造应用程序的最重要的几个类别都衍生自CCmdTarget。
2)标准消息:除WM_COMMAND 之外,任何以WM_ 开头的都算是这一类。任何衍生自CWnd 之类别,均可接收此消息。
3)Control Notification:这种消息由控制组件产生,为的是向其父窗口通知某种情况。如当你在ListBox上选择其中一个项目,ListBox就会产生LBN_SELCHANGE 传送给父窗口;这类消息也是以WM_COMMAND形式呈现[注]。
注:以前的控件是发WM_COMMAND消息,而新的控件发WM_NOTIFY消息。
2、DECLARE_MESSAGE_MAP()
相当于声明了这样的数据结构:
其中,pBaseBap 指向“基类的消息映射表”的指针。派生类自动继承基类所能处理的消息的能力。
宏展开示例[1,P415]
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_WM_CREATE()
ON_WM_PAINT()
END_MESSAGE_MAP()
宏开后,成为:
const AFX_MSGMAP* CMyView::GetMessageMap() const
{ return &CMyView::messageMap; }
AFX_DATADEF const AFX_MSGMAP CMyView::messageMap =
{ &CView::messageMap, &CMyView::_messageEntries[0] };
const AFX_MSGMAP_ENTRY CMyView::_messageEntries[] =
{
{ WM_CREATE, 0, 0, 0, AfxSig_is, \
(AFX_PMSG)(AFX_PMSGW)(int (AFX_MSG_CALL CWnd::*)(LPCREATESTRUCT))OnCreate },
{ WM_PAINT, 0, 0, 0, AfxSig_vv, \
(AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(void))OnPaint },
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 }
};
3、MFC消息传递网
Message Map 既可说是一套宏,也可以说是宏展开后所代表的一套数据结构;甚至也可以说Message Map 是一种动作,寻找与消息相吻合的项目(处理函数),从而获得消息的处理例程的函数指针。
4、为什么消息处理的流程不用虚函数实现,而要选用这种机制?
你产生一个与窗口有关的C++ 类别,然后为此窗口所可能接收的任何消息都提供一个对应的虚拟函数。这的确散发着C++ 的味道和对象导向的精神,为什么不呢?
要知道,虚拟函数必须经由一个虚拟函数表(virtual function table,vtable)实作出来,每一个子类别必须有它自己的虚拟函数表,其内至少有父类别之虚拟函数表的内容复本。虚拟函数表中的每一个项目都是一个函数指针,价值4 字节,如果基础类别的虚拟函数表有100个项目,经过10层继承,开枝散叶,总共需耗费多少内存在其中?最终,系统会被巨大的额外负担(overhead)拖垮!
5、通常消息都是停留在消息队列中等待被所隶属之窗口抓取,如果设立hook,就可以更早一步抓取消息,并且可以抓取不属于你的消息,送往你设定的一个所谓「滤网函数(filter)」。
DispatchMessage推送消息的实际流程:
6、注意两样东西:MessageMapFunctions 和AfxSig_。AfxSig_ 定义于AFXMSG_.H 档;MessageMapFunctions 定义于 WINCORE.CPP 档。
7、所有UI 对象状态的维护可以依赖所谓的UPDATE_COMMAND_UI 消息。,每当菜单被拉下并尚未显示之前,其命令项(以及对应之工具栏按钮)都会收到UPDATE_COMMAND_UI 消息,这个消息和WM_COMMAND 有一样的绕行路线,我们(程序员)只要在适当的类别中放置其处理函数,并在函数中做某些判断,便可决定如何显示命令项。
参考
[1] 深入浅出MFC
[2] MFC Technical Notes
http://msdn.microsoft.com/en-us/library/h6h0eact%28VS.80%29.aspx
[3] http://blog.163.com/zhoumhan_0351/blog/static/3995422720103821847339/
[4] http://www.cnblogs.com/mydomain/archive/2010/09/27/1837103.html
[5] http://kaweh.candy.blog.163.com/blog/static/36818772200862904354131/
[6] http://www.cnblogs.com/chinazhangjie/archive/2010/08/19/1803149.html