Windows编程基础–第19节 MFC之自定义消息
windows程序中最重要的就是消息机制,前面几节我们都是使用Windows系统设定好的消息进行编程,今天我们来使用自定义的消息来看看MFC中消息的传递过程;
MFC中自定义消息有两种方法:
- #define WM_MY_DEFINED_MSG (WM_USR+100)
- RegisterWindowMessage(WM_MY_REGISTER_MSG_SRR)
下面我们来尝试一下这两种方法有什么不同;
1. 新建项目
新建一个基于对话框项目“day21”,布局如下,自行处理:
2.第一种自定义消息
2.1 定义消息ID
我们来到day20Dlg.h 的头文件中,在上方创建一个宏定义如下:
1 | #define WM_MY_FRIST_MSG (WM_USER + 100) |
这里我们定义了一个WM_MY_FRIST_MSG整型数值,它的值时WM_USER + 100,其中WM_USER 是微软定义好的宏,它的值是:#define WM_USER 0x0400
,这说明在0x0400之前的消息(包含0x0400)都已经被windows系统使用,我们自定义消息只能在这之后,所以我们加上了100;
2.2 映射消息函数
我们切换到day20Dlg.cpp中,找到下面这地方:1
2
3
4
5BEGIN_MESSAGE_MAP(Cday21Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
这就是消息的关系图,我们来添加一条映射,如下:
1 | BEGIN_MESSAGE_MAP(Cday21Dlg, CDialogEx) |
ON_MESSAGE(WM_MY_FRIST_MSG, &Cday21Dlg::OnMyFirstMsgTrigger)
说明将WM_MY_FRIST_MSG消息ID与类Cday21Dlg的OnMyFirstMsgTrigger成员函数对应,当WM_MY_FRIST_MSG消息被触发时将调用OnMyFirstMsgTrigger方法;
2.3 实现消息函数
我们先切换到Cday21Dlg类中,添加OnMyFirstMsgTrigger方法的声明:
afx_msg LRESULT OnMyFirstMsgTrigger(WPARAM wParam, LPARAM lParam);
这是消息映射函数的固定格式,参数类型也是固定的;
接下来我们实现OnMyFirstMsgTrigger的定义,如下:
1 | LRESULT Cday21Dlg::OnMyFirstMsgTrigger(WPARAM wParam, LPARAM lParam) |
代码解释:
- 只要执行这个函数就会弹窗显示消息名称和ID;
2.4 发送消息
我们双击资源界面上的“自定义消息ID”按钮,编辑其点击事件处理函数:
1 | void Cday21Dlg::OnBnClickedBtnDefined() |
代码解释:
- 使用PostMessage发送WM_MY_FRIST_MSG消息;
2.5 运行结果
3.第二种自定义消息
3.1 定义消息ID
由于我们需要使用RegisterWindowMessage(LPCSTR lpString)来创造消息ID,所以我们需要先定义一个字符串:
1 | #define WM_MY_REGISTER_MSG_SRR _T("WM_MY_REGISTER_MSG_SRR") |
接下来我们定义一个全局变量WM_MY_REGISTER_MSG来作为消息ID;
1 | UINT WM_MY_REGISTER_MSG; |
接下来我们来初始化消息ID,我们到Cday21Dlg类的构造函数中来创建消息ID:
1 | Cday21Dlg::Cday21Dlg(CWnd* pParent /*=NULL*/) |
这样我们就通过RegisterWindowMessage来创建了消息ID,但只有在程序运行时我们才会知道消息ID是多少,并且每次运行时都可能不同;
3.2 映射消息函数
我们切换到day20Dlg.cpp中,我们再来添加一条映射,如下:
1 | BEGIN_MESSAGE_MAP(Cday21Dlg, CDialogEx) |
ON_REGISTERED_MESSAGE(WM_MY_REGISTER_MSG, &Cday21Dlg::OnMyRegisterMsgTrigger)
说明将WM_MY_REGISTER_MSG消息ID与类Cday21Dlg的OnMyRegisterMsgTrigger成员函数对应,当WM_MY_REGISTER_MSG消息被触发时将调用OnMyRegisterMsgTrigger方法;
注意:RegisterWindowMessage方法获取的消息需要用ON_REGISTERED_MESSAGE映射消息
3.3 实现消息函数
我们先切换到Cday21Dlg类中,添加OnMyRegisterMsgTrigger方法的声明:
afx_msg LRESULT OnMyRegisterMsgTrigger(WPARAM wParam, LPARAM lParam);
这是消息映射函数的固定格式,参数类型也是固定的;
接下来我们实现OnMyRegisterMsgTrigger的定义,如下:
1 | LRESULT Cday21Dlg::OnMyRegisterMsgTrigger(WPARAM wParam, LPARAM lParam) |
代码解释:
- 只要执行这个函数就会弹窗显示消息名称和ID;
2.4 发送消息
我们双击资源界面上的“REGISTER消息ID”按钮,编辑其点击事件处理函数:
1 | void Cday21Dlg::OnBnClickedBtnReg() |
代码解释:
- 使用PostMessage发送WM_MY_REGISTER_MSG消息;
2.5 运行结果
4.对比两种方法
从上面两种方法我们可以看出其优缺点:
- #define WM_MY_DEFINED_MSG (WM_USR+100)
定义的消息ID唯一,但不确定消息ID是否被其它地方占用,可能造成隐患;- RegisterWindowMessage(WM_MY_REGISTER_MSG_SRR)
优点:定义的消息ID唯一,独立;缺点:在程序运行前不能确定消息ID,不方便在其它程序中指定触发此消息ID;