第19节 MFC之自定义消息
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中,找到下面这地方:
12345BEGIN_MESSAGE_MAP(Cday21Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON()END_MESSAGE_MAP()
这就是消息的关系图,我们来添加一条映射,如下:
123456BEGIN_MESSAGE_MAP(Cday21Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(WM_MY_FRIST_MSG, &Cday21Dlg::OnMyFirstMsgTrigger)END_MESSAGE_MAP()
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的定义,如下:
1234567LRESULT Cday21Dlg::OnMyFirstMsgTrigger(WPARAM wParam, LPARAM lParam){ TCHAR szBuf[128]; _stprintf(szBuf,_T("消息:%s 被触发,消息ID: 0x%x "),_T("WM_MY_FRIST_MSG"),WM_MY_FRIST_MSG); AfxMessageBox(szBuf); return 0;}
代码解释:
只要执行这个函数就会弹窗显示消息名称和ID;
2.4 发送消息我们双击资源界面上的“自定义消息ID”按钮,编辑其点击事件处理函数:
123456void Cday21Dlg::OnBnClickedBtnDefined(){ // TODO: 在此添加控件通知处理程序代码 PostMessage(WM_MY_FRIST_MSG,0,0);}
代码解释:
使用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;
1UINT WM_MY_REGISTER_MSG;
接下来我们来初始化消息ID,我们到Cday21Dlg类的构造函数中来创建消息ID:
123456Cday21Dlg::Cday21Dlg(CWnd* pParent /*=NULL*/) : CDialogEx(Cday21Dlg::IDD, pParent){ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); WM_MY_REGISTER_MSG = RegisterWindowMessage(WM_MY_REGISTER_MSG_SRR);}
这样我们就通过RegisterWindowMessage来创建了消息ID,但只有在程序运行时我们才会知道消息ID是多少,并且每次运行时都可能不同;
3.2 映射消息函数我们切换到day20Dlg.cpp中,我们再来添加一条映射,如下:
123456789BEGIN_MESSAGE_MAP(Cday21Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BTN_DEFINED, &Cday21Dlg::OnBnClickedBtnDefined) ON_MESSAGE(WM_MY_FRIST_MSG, &Cday21Dlg::OnMyFirstMsgTrigger) ON_REGISTERED_MESSAGE(WM_MY_REGISTER_MSG, &Cday21Dlg::OnMyRegisterMsgTrigger) ON_BN_CLICKED(IDC_BTN_REG, &Cday21Dlg::OnBnClickedBtnReg)END_MESSAGE_MAP()
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的定义,如下:
1234567LRESULT Cday21Dlg::OnMyRegisterMsgTrigger(WPARAM wParam, LPARAM lParam){ TCHAR szBuf[128]; _stprintf(szBuf,_T("消息:%s 被触发,消息ID: 0x%x "),_T("WM_MY_REGISTER_MSG"),WM_MY_REGISTER_MSG); AfxMessageBox(szBuf); return 0;}
代码解释:
只要执行这个函数就会弹窗显示消息名称和ID;
2.4 发送消息我们双击资源界面上的“REGISTER消息ID”按钮,编辑其点击事件处理函数:
1234void Cday21Dlg::OnBnClickedBtnReg(){ PostMessage(WM_MY_REGISTER_MSG,0,0);}
代码解释:
使用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;
项目源码可以访问我的码云>>>我的私人博客<<<