MFC消息机制

Windows消息分类:

先讲下Windows消息的分类。Windows消息分为系统消息和用户自定义消息。Windows系统消息有三种:

  1.标准Windows消息。除WM_COMMAND外以WM_开头的消息是标准消息。例如,WM_CREATE、WM_CLOSE

       2.命令消息。消息名为WM_COMMAND,消息中附带了标识符ID来区分是来自哪个菜单、工具栏按钮或加速键的消息

       3.通知消息。通知消息一般由列表框等子窗口发送给父窗口,消息名也是WM_COMMAND,其中附带了控件通知码来区分控件

       CWnd的派生类都可以接收到标准Windows消息、通知消息和命令消息。命令消息还可以由文档类等接收

       用户自定义消息是实际上就是用户定义一个宏作为消息,此宏的值应该大于等于WM_USER,然后此宏就可以跟系统消息一样使用,窗口类中可以定义它的处理函数

 

消息映射表:

除了一些没有基类的类或CObject的直接派生类外,其他的类都可以自动生成消息映射表。下面的讲解都以前面例程HelloWorld的CMainFrame为例。消息映射表如下:

C++代码

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)   

    ON_WM_CREATE()   

    ON_COMMAND(ID_VIEW_CUSTOMIZE, &CMainFrame::OnViewCustomize)   

    ON_REGISTERED_MESSAGE(AFX_WM_CREATETOOLBAR, &CMainFrame::OnToolbarCreateNew)   

    ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)   

    ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)   

    ON_WM_SETTINGCHANGE()   

END_MESSAGE_MAP()  

 

在BEGIN_MESSAG_MAP和END_MESSAGE_MAP之间的内容成为消息映射入口项。消息映射除了在CMainFrame的实现文件中添加消息映射表外,在类的定义文件MainFrm.h中还会添加一个宏调用:

DECLARE_MESSAGE_MAP()

一般这个宏调用写在类定义的结尾处

 

添加消息处理函数:

如何添加消息处理函数呢?不管是自动还是手动添加都有三个步骤:

       1.在类定义中加入消息处理函数的函数声明,注意要以afx_msg打头。例如MainFrm.h中WM_CREATE的消息处理函数的函数声明:afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct)

       2.在类的消息映射表中添加该消息的消息映射入口项。例如WM_CREATE的消息映射入口项:ON_WM_CREATE()

       3.在类实现中添加消息处理函数的函数实现。例如,MainFrm.cpp中WM_CREATE的消息处理函数的实现:

          int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
         {
                  ......
         }

       通过以上三个步骤以后,WM_CREATE等消息就可以在窗口类中被消息处理函数处理了

 

 

ON_COMMAND 和ON_MESSAGE都是将消息处理函数加入消息路由表中

ON_COMMAND用来处理WM_COMMAND消息。老式的windows控件发送WM_COMMAND作为对父窗口的通知消息。另外,菜单,工具栏也向框架窗口发送WM_COMMAND消息

ON_MESSAGE主要用来处理用户自定义消息。对于某些新型的windows控件(如ListCtrl等),向父窗口发送通知消息时需要包含大量的信息,WM_COMMAND已不适应这种要求(因为WM_COMMAND的wparam和lparam都已经填满了)

ON_NOTIFY主要用来处理这些新型的windows控件向父窗口的发送的WM_NOTIFY通知消息

 

Window消息的背景:

  在Windows3.1里,控件会将mouse,   keybord等等的消息通知它的父窗口,使用的消息就只有WM_COMMAND,  事件种类和控件ID被包含在wParam中,控件的句柄包含在lParam中。由于wParam和lParam已经满了,当控件要向父窗口发送其它特殊消息同时附带很多信息的时候就没有地方可以存放它们了。所以Windows3.1中定义了许多其它的消息种类,比如WM_VSCROLL,   WM_CTLCOLOR等等,每种消息wParam,lParam中附带的信息是不同的

      当到了Win32后,控件的种类越来越多,当然不可以为每一个控件都定义一套消息,这样也不利于系统的扩充。所以在Win32中定义了唯一一个强大的消息WM_NOTIFY。当然WM_NOTIFY也遵守原来的消息规则,既只带参数wParam和lParam。唯一不同处在于,此时的lParam中传送的是一个NMHDR指针。不同的控件可以按照规则对NMHDR进行扩充,因此WM_NOTIFY消息传送的信息量可以相当的大,这个可以看看MSDN中的相关说明,TreeControl中就有很多这种消息。

  现在就可以知道为什么有ON_MESSAGE、ON_COMMAND、 ON_NOTIFY了

  ON_MESSAGE是处理所有的Windows的消息的,因为所有的消息都以相同的格式传送,也就是ID,   WPARAM,  LPARAM  

  ON_COMMAND是专门处理WM_COMMAND消息的,这样我们就不用自己解开WM_COMMAND中wParam和lParam中传送的控件ID,事件种类…,所有的都在MFC内部解决了:),当然方便了

  ON_NOTIFY更是不用说了,看看他的处理函数,是不是把NMHDR解出来了
 

  这样一样就一目了然了,ON_COMMAND和ON_NOTIFY都可以用ON_MESSAGE来处理,只不过自己要多做很多事情。ON_COMMAND和ON_NOTIFY最好就不要互换了! 

 

 

参考链接:https://blog.csdn.net/cnhk1225/article/details/47087879

     http://www.jizhuomi.com/software/147.html

posted on 2019-03-12 20:30  Cynthia_W  阅读(208)  评论(0编辑  收藏  举报