第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;

    项目源码可以访问我的码云>>>我的私人博客<<<