文章目录
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();
}