【上位机——MFC】消息映射机制

发布于:2025-04-23 ⋅ 阅读:(13) ⋅ 点赞:(0)

MFC框架利用消息映射机制把消息、命令与它们的处理函数映射起来。具体实现方法是在每个能接收和处理消息的类中,定义一个消息和消息函数指针对照表,即消息映射表。

在不重写WindowProc虚函数的大前提下,仍然可以处理消息。

Window消息分类

  1. 标准Windows消息:除WM_COMMAND外以WM_开头的消息都是标准消息。
  2. 命令消息:消息名为WM_COMMAND,消息中附带了标识符ID来区分来自哪个菜单、工具栏按钮或加速键的消息。
  3. 通知消息:通知消息一般由列表框等子窗口发送给父窗口,消息名也是WM_COMMAND,其中附带了控件通知码来区分控件。
  4. 用户自定义消息:用户定义一个宏作为消息,值大于WM_USER。

CWnd的派生类可以接收者四种消息,命令消息还可以由文档类接收。
命令消息的处理顺序:框架类(CFrameWnd派生类)优先于应用程序类(CWinApp派生类)。视图类(CView派生类)优先于框架类(CFrameWnd派生类)。

消息映射可以通过VS2022的菜单项自动生成
项目-》类向导 选择你需要再哪个类中添加对应的消息。
如下图:
在这里插入图片描述

消息映射机制的使用

  1. 类内必须添加声明宏
    DECLARE_MESSAGE_MAP() 
    
  2. 类外必须添加实现宏
    BEGIN_MESSAGE_MAP(theClass,baseClass)
    END_MESSAGE_MAP()
    

当一个类具备上述两个条件,这个类就可以按照消息映射机制来处理消息。

代码示例

#include <afxwin.h>
#include "resource.h"

//自定义消息
#define WM_MYMESSAGE WM_USER+1001

//1.定义自己的框架类CMyFrameWnd,派生自CFrameWnd类
class CMyFrameWnd :public CFrameWnd {

	DECLARE_MESSAGE_MAP()

public:
	afx_msg int OnCreate(LPCREATESTRUCT param);
	afx_msg void OnPaint(void);
	afx_msg void OnMouseMove(UINT nKey, CPoint pt);

	afx_msg LRESULT OnMyMessage(WPARAM wParam,LPARAM lParam);

	afx_msg void OnOpen();

	
	afx_msg void OnInitMenuPopup(CMenu* pPopup,UINT nPos, BOOL i);
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);

	int m_x;
	int m_y;

	CMenu menu;
		 
	
};

BEGIN_MESSAGE_MAP(CMyFrameWnd,CFrameWnd)

	//使用标准消息实现WM_CREATE (窗口创建)消息的处理
	ON_WM_CREATE()
	//使用标准消息实现WM_PAINT(绘图)消息的处理
	ON_WM_PAINT()
	//使用标准消息实现鼠标移动消息
	ON_WM_MOUSEMOVE()

	//自定义消息
	ON_MESSAGE(WM_MYMESSAGE,OnMyMessage)

	//命令消息
	ON_COMMAND(ID_OPEN, &CMyFrameWnd::OnOpen)
	//标准消息
	ON_WM_INITMENUPOPUP()
	//标准消息
	ON_WM_CONTEXTMENU()
END_MESSAGE_MAP()



//ON_WM_CREATE消息调用的函数
int CMyFrameWnd::OnCreate(LPCREATESTRUCT param) {

	//加载菜单方式二
	menu.LoadMenu(IDR_MENU1);
	this->SetMenu(&menu);

	AfxMessageBox("ON_WM_CREATE");
 	//发送自己定义的消息
	::PostMessage(this->m_hWnd, WM_MYMESSAGE, 1, 2);

	return CFrameWnd::OnCreate(param);
}

//ON_WM_PAINT消息调用的函数
void CMyFrameWnd::OnPaint(void) {
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
	::TextOutA(hdc, m_x, m_y, "hello", 5);
	::EndPaint(m_hWnd, &ps);
}

//OnMouseMove消息调用的函数
void CMyFrameWnd::OnMouseMove(UINT nKey, CPoint pt) {
	m_x = pt.x;
	m_y = pt.y;
	//hello 字符串跟着鼠标移动
	::InvalidateRect(this->m_hWnd, NULL, TRUE);

}
//自定义消息
LRESULT CMyFrameWnd::OnMyMessage(WPARAM wParam, LPARAM lParam) {
	CString str;
	str.Format("wParam=%d, lParam=%d", wParam, lParam);

	AfxMessageBox(str);
	return 0;
}

//命令消息 点击打开
void CMyFrameWnd::OnOpen()
{
	AfxMessageBox("ON_COMMAND");
}

//设置菜单状态
void CMyFrameWnd::OnInitMenuPopup(CMenu* pPopup, UINT nPos, BOOL i) 
{
	//ID为ID_OPEN的菜单项前面打对号
	pPopup->CheckMenuItem(ID_OPEN,MF_CHECKED);
}

//鼠标右键
void CMyFrameWnd::OnContextMenu(CWnd* pWnd, CPoint point)
{
	//HMENU hPopup = ::GetSubMenu(menu.m_hMenu,0);
	//展示菜单
	//::TrackPopupMenu(hPopup,TPM_LEFTALIGN|TPM_TOPALIGN,point.x,point.y,0,this->m_hWnd,NULL);
	//上下两种方式均可
	CMenu* pPopup = menu.GetSubMenu(0);
	//展示菜单
	pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_TOPALIGN, point.x, point.y,this);
}


//定义自己应用程序类CMyWinApp,派生自CWinApp类,
//并定义构造以及重写InitInstance虚函数,在函数中创建并显示窗口
class CMyWinApp :public CWinApp {

public :
	CMyWinApp() {}

	virtual BOOL InitInstance() {
	
		CMyFrameWnd* pFrame = new CMyFrameWnd;

		//最后一个参数 加载菜单方式一(常用)
		//pFrame->Create(NULL,"MFCBase",WS_OVERLAPPEDWINDOW,CFrameWnd::rectDefault,NULL,(CHAR*)IDR_MENU1);
		pFrame->Create(NULL, "MFCBase");

		m_pMainWnd = pFrame;
		pFrame->ShowWindow(SW_SHOW);
		pFrame->UpdateWindow();

		return TRUE;
	
	}
};

//3.定义CMyWinApp类的对象(程序的爆破点)
CMyWinApp theApp;


网站公告

今日签到

点亮在社区的每一天
去签到