VC++学习笔记之MFC消息映射机制
1、MFC消息映射机制的具体实现方法是:在每个能接收和处理消息的类中,定义一个消息和消息函数静态对照表,即消息映射表。在消息映射表中,消息与对应的消息函数指针是成对出现的。某个类能处理的所有消息及其对应的消息处理函数的地址都列在这个类所对应的静态表中。当有消息需要处理时,程序只要搜索该消息静态表,查看表中是否含有该消息,就可知道该类能否处理此消息。如果能处理该消息,则同样依照静态表能很容易找到并调用对应的消息处理函数。
2、MFC消息映射机制处理有三处相关信息:函数原型、函数实现,以及用来关联消息和消息响应函数的宏。其中,函数原型是在类的头文件中,在注释宏之间;函数实现在类的源文件处,是消息响应函数的实现代码;消息映射宏在类的源文件处,在两个AFX_MSG_MAP注释宏之间,通过这个宏把消息与消息响应函数关联起来。
3、代码实例
第一部分“DrawView.h”头文件,“函数原型声明”
//DrawView.h : interface of the CDrawView class
//
////////////////////////////////////////////////////////////
class CDrawView : public CView
{
protected: // create from serialization only
CDrawView();
DECLARE_DYNCREATE()
...................................
//Generated message map funtions
protected:
//{{AFX_MSG(CDrawView)
afx_msg void OnLButtonDown(UINT nFlags , CPoint point); //函数原型声明
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
}
第二部分“DrawView.cpp”中的“消息映射宏”和“消息响应函数”
//DrawView.cpp : implementation of the CDrawView class
IMPLEMENT_DYNCREATE(CDrawView, CView)
BEGIN_MESSAGE_MAP(CDrawView , CView)
//{{AFX_MSG_MAP(CDrawView)
ON_WM_LBUTTONDOWN() //消息映射宏
//}}AFX_MSG_MAP
//Standard printing commands
ON_COMMAND(ID_FILE_PRINT,CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT,CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW,CView::OnFilePrintPreview)
END_MESSAGE_MAP()
//CDrawView message handlers
void CDrawView : : OnLButtonDown(UINT nFlags , CPoint point) //消息响应函数的实现
{
// TODO: Add your message handler code here and/or call default
MessageBox("View Clicked!");
CView::OnLButtonDown(nFlags,point);
}
4、MFC消息映射机制的实际实现过程
(1)MFC在后台维护了一个窗口句柄与对应的C++对象指针的对照表。窗口有一个句柄,该句柄与CDrawView对象的一个指针(即 CDrawVew*)存在着一一对应关系,在C++对象对照表中维护了这种对应关系。当收到消息,消息的第一个参数就是句柄参数。获取窗口句柄后,根据对照表找到与之相关的C++对象指针。然后将指针传递给应用程序框架窗口类的基类,改基类会调用一个名为WindowProc的函数。
(2)其实WindowProc函数只是一个虚函数。在它内部调用了一个OnWndMsg函数,该函数完成了真正的消息路由,也就是真正的完成了消息映射。该函数位于WinCore.cpp文件中。
(3)OnWndMsg函数的处理过程:
首先判断消息是否有消息响应函数。判断方法是根据窗口子类指针,在子类的头文件中查找看看DECLARE_MESSAGE_MAP()宏之上,两个AFX_MSG注释之间是否具有相应的响应函数原型的声明;再到子类的源文件中,看看BEGIN_MESSAGE_MAP和END_MESSAGE_MAP()这两个宏之间是否有相应的消息映射宏。如果通过消息映射宏找到了消息响应函数,那么就调用该响应函数,对消息进行处理。如果没有找到,则由基类处理。
本片文章参考了《VC++深入理解》(孙鑫老师)
朋友,如果您有什么真知灼见,可以加“新浪微博”/MSN哦,starrycheng@live.com,我们大家一起讨论,一起研究。
最后,帮忙加一分吧,想整个空间系统。