【MFC】消息映射机制

MFC消息映射机制

总所周知,Windows应用程序都是消息驱动的在MFC软件开发中,界面操作或者线程之间通信都会经常用到消息,通过对消息的处理实现相应的操作。比较典型的过程是,用户操作窗口,然后有消息产生,送给窗口的消息处理函数处理,对用户的操作做出响应。
今天就来简单聊一聊MFC中的消息映射机制。MFC消息映射图

  1. 第一步:用户通过标准输入发送消息给操作系统。
  2. 第二步:操作系统将消息丢进消息队列中,进行排队。
  3. 第三步:响应的应用程序得到消息,也就是GetMessage();
  4. 第四步:应用程序会发送消息(不含组合键)DispatchMessage(),如果有组合键,比如shift+alt等等,则应用程序会先通过TranslateMessage函数翻译消息,然后丢给消息队列重新排队。
  5. 第五步:应用程序将消息给操作系统执行消息。

什么是消息?

窗口消息一般由三个部分组成:1.一个无符号整数,是消息值;(2)消息附带的WPARAM类型的参数;(3)消息附带的LPARAM类型的参数。其实我们一般所说的消息是狭义上的消息值,也就是一个无符号整数,经常被定义为宏。

什么是消息映射机制

MFC使用一种消息映射机制来处理消息,在应用程序框架中的表现就是一个消息与消息处理函数一一对应的消息映射表,以及消息处理函数的声明和实现等代码。当窗口接收到消息时,会到消息映射表中查找该消息对应的消息处理函数,然后由消息处理函数进行相应的处理。SDK编程时需要在窗口过程中一一判断消息值进行相应的处理,相比之下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等消息就可以在窗口类中被消息处理函数处理了。

各种Windows消息的消息处理函数

标准Windows消息的消息处理函数都与WM_CREATE消息类似。
命令消息的消息映射入口项形式如:

ON_COMMAND(ID_VIEW_CUSTOMIZE, &CMainFrame::OnViewCustomize)
   ,消息为	ID_VIEW_CUSTOMIZE,消息处理函数为OnViewCustomize。
   如果想要使用某个处理函数批量处理某些命令消息,则可以像CMainFrame消息映射表中的一样
ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)

添加消息映射入口项,这样值在ID_VIEW_APPLOOK_WIN_2000到ID_VIEW_APPLOOK_WINDOWS_7之间的菜单项等的命令消息都由CMainFrame的OnApplicationLook函数处理。函数原型为afx_msg void OnApplicationLook(UINT id);,参数id为用户操作的菜单项等的ID。
在操作列表框等控件时往往会给父窗口发送WM_NOTIFY通知消息。WM_NOTIFY消息的wParam参数为发送通知消息的控件的ID,lParam参数指向一个结构体,可能是NMHDR结构体,也可能是第一个元素为NMHDR结构体变量的其他结构体。NMHDR结构体的定义如下(仅作了解):

   Typedef sturct tagNMHDR{
                HWND hwndFrom;
                UINT idFrom;
                UINT code;
       } NMHDR;
   hwndFrom为发送通知消息控件的句柄,idFrom为控件ID,code为要处理的通知消息的通知码,例如NM_CLICK。

   通知消息的消息映射入口项形式如:
   ON_NOTIFY(wNotifyCode,id,memberFxn)
   wNotifyCode为要处理的通知消息通知码,例如:NM_CLICK。id为控件标识ID。MemberFxn为此消息的处理函数。
   通知消息的处理函数的原型为:
   afx_msg void memberFxn( NMHDR * pNotifyStruct, LRESULT * result);
   如果需要使用用户自定义消息,首先要定义消息宏,如:#define WM_UPDATE_WND (WM_USER+1),再到消息映射表中添加消息映射入口项:ON_MESSAGE(WM_UPDATE_WND, &CMainFrame::OnUpdateWnd),然后在MainFrm.h中添加消息处理函数的函数声明:afx_msg LRESULT OnUpdateWnd(WPARAM wParam, LPARAM lParam);,最后在MainFrm.cpp中实现此函数。

本文只是对MFC消息映射机制做简单了解,入门其实不必太过计较这个机制,用多了,自然就知道怎么回事了,这样说反而显得有些abstract.
有兴趣的小伙伴可以私我,交流交流,我也是MFC学了不久。谢谢大家!

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MFC(Microsoft Foundation Classes)是一组用于开发 Windows 应用程序的 C++ 类库。在 MFC 中,消息映射是一种机制,用于将 Windows 消息与相应的消息处理函数关联起来。 消息映射是通过在类的消息映射表中定义消息处理函数来实现的。消息映射表是一个由宏定义和消息映射项组成的静态数组。每个消息映射项指定了一个 Windows 消息的 ID 和相应的消息处理函数。 消息处理函数是类中的成员函数,用于处理特定的 Windows 消息。当一个窗口接收到一个消息时,MFC 会根据消息映射表中的定义找到对应的消息处理函数,并执行该函数来处理该消息。 下面是一个简单的示例,展示了如何使用消息映射消息处理函数: ```cpp // 声明消息映射表 BEGIN_MESSAGE_MAP(CMyWnd, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() // 定义消息处理函数 void CMyWnd::OnPaint() { // 处理 WM_PAINT 消息 // ... } void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point) { // 处理 WM_LBUTTONDOWN 消息 // ... } ``` 在上面的示例中,`CMyWnd` 是一个继承自 `CWnd` 的自定义窗口类。通过在消息映射表中使用 `ON_WM_PAINT` 宏和 `ON_WM_LBUTTONDOWN` 宏,将 `OnPaint` 函数和 `OnLButtonDown` 函数与 `WM_PAINT` 消息和 `WM_LBUTTONDOWN` 消息关联起来。 当窗口接收到相应的消息时,就会调用对应的消息处理函数进行处理。 需要注意的是,消息映射表中的消息处理函数必须是类的成员函数,并且符合特定的函数签名。 希望这个简单的解释能够帮助你理解 MFC 中的消息映射消息处理机制。如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cain Xcy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值