一 新建MFC项目(单文档,MFC标准)后,在类视图CMainFrame右键->类向导->消息-列表中找到 WM_LBUTTONDOWN 双击或者右边按钮 添加处理程序(A), 则添加了一个响应按下鼠标左键的一个消息。
还是类向导对话框中,消息选项卡现有处理程序中,双击OnLButtonDown或者单击右边按钮 编辑代码。自动转到代码部分。
在代码里面添加一句代码用来弹处一个消息框: MessageBoxA(NULL,"Hello","提示",0);
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 MessageBoxA(NULL,"Hello","提示",0); CView::OnLButtonDown(nFlags, point); }
运行程序后,在弹处的界面的任何地方单击左键,都没有消息框弹出来。
二 在类视图选项卡上,xxxxView类上,右键->类向导.....同上面的步骤,添加一个消息.
void CMFCApplication3View::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此添加消息处理程序代码和/或调用默认值 MessageBoxA(NULL,"Hello","提示",0); CView::OnLButtonDown(nFlags, point); }
此时在单击,正常弹处对话框! 原因是View总是在CMainFrame的最顶层。
三 CMainFrame上添加的OnLButtonDown没用,删除方法:类视图->CMainFrame上右键->类向导->消息选项卡->在现有处理程序选中要删除的OnLButtonDown 单击右边按钮删除处理程序即可.因为手动删除可能导致出错,因为一条消息的创建,在MFC中,会在好几个地方添加关联代码。
四 MFC消息创建过程
4.1.xxxxView.h头文件中,有一句添加了一句 afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg是一个宏,它表示修饰的函数表示是一个消息响应函数的声明,声明在DECLARE_MESSAGE_MAP()前或后效果相同,VS2015默认放在后面,“}”“之前。
4.2 xxxxView.cpp文件中,BEGIN_MESSAGE_MAP(CMFCApplication3View, CView)与END_MESSAGE_MAP()中间增加了一条宏ON_WM_LBUTTONDOWN()。代码如下:
BEGIN_MESSAGE_MAP(CMFCApplication3View, CView) // 标准打印命令 ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview) ON_WM_CREATE() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP()
4.3 ON_WM_LBUTTONDOWN() 实现消息和消息响应函数void CMFCApplication3View::OnLButtonDown(UINT nFlags, CPoint point)连接起来了。当有WM_LBUTTONDOWN消息来的时候,自动调用该函数。
4.4 Win32程序中 消息产生----->消息队列---->应用程序用GetMessage()从队列中提取消息,通过DispacthMessage() 把消息派发给操作系统,操作系统再去调用消息处理函数对消息进行处理。
4.5 MFC中看上去,按照以上步骤添加消息关联代码,就能正确响应消息,看上去流程跟Win32的消息处理流程不同。
可以在基类中,针对每个消息定义了一个虚函数,子类只要重写这个虚函数,就可以实现,但在MFC中,继承层次很多,100多消息,每个继承它的子类,都会有一张虚表, 针对每个消息写虚函数,这样它会变得很庞大,也是对资源的一种浪费。
MFC在后台维护了一个句柄和C++对象指针的一个对照表,一旦有消息了产生,它就可以知道这个消息跟哪个窗口相关的,通过句柄找到相对应的C++对象指针,并将该指针传递给基类,基类调用消息循环,最终通过调用WindowProc(WINCORE.CPP)对该消息进行处理,WindowProc是一个虚函数,在它的内部再调用后一个OnWndMsg()函数处理的,在OnWndMsg内部完成对消息映射的一个处理,本质上没有区别。