Bootstrap

windows第五章 MFC基本消息和消息映射介绍

MFC基本消息和消息映射介绍

编写消息映射

在之前的CMyDlg.h修改

#pragma once
#include "stdafx.h"
class CMyDlg :
	public CDialog
{
public:
	CMyDlg();
	//声明消息映射
	DECLARE_MESSAGE_MAP()
public:
		BOOL OnInitDialog();
		int OnCreate(LPCREATESTRUCT lpCreateStruct);//重写基本消息
};

CMyDlg.cpp

#include "CMyDlg.h"

CMyDlg::CMyDlg()
	:CDialog(IDD_MAIN_DIALOG)
{
}

//开始消息映射
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
	ON_WM_CREATE() //要重写哪个就在这里添加哪个
END_MESSAGE_MAP()
//结束消息映射

BOOL CMyDlg::OnInitDialog()
{
	SetWindowText(L"My Dialog");
	return TRUE;
}

int CMyDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{

	return CDialog::OnCreate(lpCreateStruct);
}

常用消息

#include "CMyDlg.h"
#define TIME_TIMER_ID 1
#define GAME_TIMER_ID 2
CMyDlg::CMyDlg()
	:CDialog(IDD_MAIN_DIALOG)
{
	m_hIcon1 = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICONqq));
	m_hIcon2 = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICONwendi));
}

//开始消息映射
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
	ON_WM_CREATE() //创建消息
	ON_WM_CLOSE()//关闭消息
	ON_WM_DESTROY()//销毁消息
	ON_WM_PAINT()//绘制消息
	ON_WM_TIMER()//定时器消息
	ON_WM_SIZE()//窗口大小改变消息
	ON_WM_LBUTTONDOWN()//鼠标左键按下消息
	ON_WM_LBUTTONUP()//鼠标左键抬起消息
	ON_WM_MOUSEMOVE()//鼠标移动消息
END_MESSAGE_MAP()
//结束消息映射

BOOL CMyDlg::OnInitDialog()
{
	SetWindowText(L"My Dialog");

	//开启定时器
	SetTimer(TIME_TIMER_ID, 1000, NULL);
	SetTimer(GAME_TIMER_ID, 1000, NULL);
	//设置图标
	SetIcon(m_hIcon1, TRUE);
	SetIcon(m_hIcon1, FALSE);
	return TRUE;
}


int CMyDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{

	return CDialog::OnCreate(lpCreateStruct);
}

void CMyDlg::OnClose()
{
	if (IDYES == MessageBox(_T("确定退出吗?"), _T("提示"), MB_YESNO))
		CDialog::OnClose();
	else {
		KillTimer(TIME_TIMER_ID);//定时器关闭

	}
}

void CMyDlg::OnDestroy()
{
	MessageBox(L"窗口已经销毁,窗口不能再显示了");
	CDialog::OnDestroy();
}

void CMyDlg::OnPaint()
{
	CPaintDC dc(this);
	CRect rect;
	GetClientRect(&rect);
	dc.DrawText(L"Hello World", &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}

void CMyDlg::OnTimer(UINT_PTR nIDEvent)
{
	switch (nIDEvent)
	{
	case TIME_TIMER_ID:
	{
		//获取当前时间
		CTime time = CTime::GetCurrentTime();
		CString time_str = time.Format(L"当前时间:%Y-%m-%d %H:%M:%S");
		SetWindowText(time_str);
		break;
	}
	case GAME_TIMER_ID:
	{
		static int n = 0;
		if (n++)
		{
			SetIcon(m_hIcon1, TRUE);
			SetIcon(m_hIcon1, FALSE);
		}
		else
		{
			SetIcon(m_hIcon2, TRUE);
			SetIcon(m_hIcon2, FALSE);
		}
		n %= 2;
	}
	}
	CDialog::OnTimer(nIDEvent);
}

void CMyDlg::OnSize(UINT nType, int cx, int cy)
{
	CString str;
	str.Format(L"窗口大小改变,宽:%d,高:%d", cx, cy);
	SetWindowText(str);
	return CDialog::OnSize(nType, cx, cy);
}

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	if (nFlags & MK_CONTROL)
	{
		SetWindowText(L"同时按下了Ctrl键");
	}
	CDialog::OnLButtonDown(nFlags, point);
}

void CMyDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
	CDialog::OnLButtonUp(nFlags, point);
}

void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
{
	CString str;
	str.Format(L"鼠标移动,坐标:%d,%d", point.x, point.y);
	SetWindowText(str);
	CDialog::OnMouseMove(nFlags, point);
}

删除消息映射函数

比如删除定时器消息映射
把 ON_WM_TIMER() 注释掉就行了

发送消息

SendMessage和PostMessage,在之前章节讲过
这里写一个自定义消息发送的案例

#include "CMyDlg.h"
#define UM_EAT WM_USER+1 //自定义消息
CMyDlg::CMyDlg()
	:CDialog(IDD_MAIN_DIALOG)
{
	m_hIcon1 = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICONqq));
	m_hIcon2 = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_ICONwendi));
}

//开始消息映射
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
	ON_WM_LBUTTONDOWN()//鼠标左键按下消息
	ON_MESSAGE(UM_EAT, &OnEat)//自定义消息
END_MESSAGE_MAP()
//结束消息映射

BOOL CMyDlg::OnInitDialog()
{
	SetWindowText(L"My Dialog");
	//设置图标
	SetIcon(m_hIcon1, TRUE);
	SetIcon(m_hIcon1, FALSE);
	return TRUE;
}

void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
	if (nFlags & MK_CONTROL)
	{
		SetWindowText(L"同时按下了Ctrl键");
	}
	//发送自定义消息
	int res = SendMessage(UM_EAT, 100, 200);
}


LRESULT CMyDlg::OnEat(WPARAM wParam, LPARAM lParam)
{
	CString str;
	str.Format(L"吃到了食物");
	SetWindowText(str);
	return (int)lParam + (int)wParam;
}

消息映射原理

DECLARE_MESSAGE_MAP()

宏定义可以替换如下

protected: 
	static const AFX_MSGMAP*  __stdcall GetThisMessageMap(); 
	const AFX_MSGMAP* GetMessageMap() const override; 

声明了2个函数,属性是保护的,所以在这个宏下面写其他函数声明要重写一下public:或者private:

BEGIN_MESSAGE_MAP()

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
	ON_WM_LBUTTONDOWN()//鼠标左键按下消息
END_MESSAGE_MAP()

上述宏定义代码可以替换成如下

	const AFX_MSGMAP* CMyDlg::GetMessageMap() const 
		{ return GetThisMessageMap(); } 
	const AFX_MSGMAP*  __stdcall CMyDlg::GetThisMessageMap() 
	{ 					   
		static const AFX_MSGMAP_ENTRY _messageEntries[] =  
		{
		{ WM_LBUTTONDOWN, 0, 0, 0,
		 AfxSig_vwp, (AFX_PMSG)(AFX_PMSGW)(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > ( &CMyDlg:: OnLButtonDown)) },
	
		{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } 
		}; 
		static const AFX_MSGMAP messageMap = 
		{ &CDialog::GetThisMessageMap, &_messageEntries[0] }; 
		return &messageMap; 
	}								  

就是对之前声明的函数的定义,就相当于包装了一下win32的消息,进行处理

使用工具直接建立MFC对话框

在这里插入图片描述

非模态对话框

模态对话框的创建

void CdemoDlg::OnBnClickedOk()
{
	// TODO: 在此添加控件通知处理程序代码
	//弹出模态对话框
	CAboutDlg dlg;
	int res = dlg.DoModal();//阻塞函数,会阻塞主线程,直到对话框关闭
	if (res == IDOK)
		AfxMessageBox(_T("你点击了确定"));
	else if (res == IDCANCEL)
		AfxMessageBox(_T("你点击了取消"));

}

非模态创建

void CdemoDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	CChatDlg* pDlg = new CChatDlg(this);
	pDlg->Create(IDD_CHAT_DIALOG, this);
	pDlg->ShowWindow(SW_SHOW);
}

销毁new出来的内存

void CChatDlg::PostNcDestroy()
{
	// TODO: 在此添加专用代码和/或调用基类
	delete this;

	CDialogEx::PostNcDestroy();
}
;