消息映射机制
1.Win32消息
在win32中,一个窗口的所有操作都是通过消息机制完成的,如下
c++
#include <windows.h>
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
case WM_PAINT:
return 0;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)
{
// ............
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}MFC的消息处理机制是基于消息映射(MessageMap)的,它允许开发者将特定的Windows消息映射到特定的成员函数(称为消息处理函数)上。
2.MFC消息映射步骤
2.1 声明消息映射
DECLARE_MESSAGE_MAP是一个宏,它必须在MFC类的头文件中声明,以便MFC框架能够识别该类具有消息映射
需要给哪个对话框声明消息映射,就在哪个对话框的头文件中声明DECLARE_MESSAGE_MAP
c++
class CMFCTEST1Dlg : public CDialogEx
{
public:
protected:
// 省略其他
DECLARE_MESSAGE_MAP() // 注意不用写分号,这是个宏
};2.2 定义消息映射
在头文件中声明消息映射后,需要在相应的cpp文件中使用BEGIN_MESSAGE_MAP和END_MESSAGE_HAP宏来定义消息映射。
c++
// 构造函数
CMFCTEST1Dlg::CMFCTEST1Dlg(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_MFC_TEST1_DIALOG, pParent)
{
// 省略
}
BEGIN_MESSAGE_MAP(CMFCTEST1Dlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
// 用来添加各种映射消息
END_MESSAGE_MAP()BEGIN_MESSAGE_MAP和END_MESSAGE_MAP也都是个宏
BEGIN_MESSAGE_MAP有两个参数- 第一个是当前对话框类的名称
- 第二个是对话框的基类的名称
- END_MESSAGE_MAP宏标记消息映射的结束。
在创建好一个MFC项目之后,两个宏之间已经自动添加了部分消息
当我们在资源视图双击一个控件时,也会自动往这两个宏之前添加一个消息映射,例如下面添加一个按钮的点击消息
c++
BEGIN_MESSAGE_MAP(CMFCTEST1Dlg, CDialogEx)
ON_BN_CLICKED(IDOK, &CMFCTEST1Dlg::OnBnClickedOk)
END_MESSAGE_MAP()给控件添加消息时
- 一般第一个参数是控件的ID,可以在属性视图看到
- 第二个是该消息处理函数的地址,这个函数会在对话框的头文件生成,下面继续
2.3 声明消息处理函数
声明消息处理函数要在相应对话框类的头文件中声明
c++
class CMFCTEST1Dlg : public CDialogEx
{
public:
CMFCTEST1Dlg(CWnd* pParent = nullptr); // 标准构造函数
// 省略其他
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk();
};afx_msg也是一个宏,它代表着此函数是一个消息处理函数
2.4 定义函数
接下来需要在对话框类相应的cpp文件中,定义刚才声明的函数
c++
void CMFCTEST1Dlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
CDialogEx::OnOK();
}以上就是MFC中,给一个空间添加事件的步骤,这些步骤一般在对话框编辑视图中,直接双击某个空间会自动生成相应控件常用的消息处理函数,例如button会生成点击事件
想要生成其他事件,可以点击属性视图中的事件页
但是MFC给一个控件自定义的消息很少,往往我们需要用到一个事件,但这个空间没有相应的自定义事件时,我们需要自己重写相应的控件类,后面会有介绍
