Home 篮球世界杯决赛 MFC 自定义 PostMessage 、SendMessage 消息

MFC 自定义 PostMessage 、SendMessage 消息

目录

一、PostMessage 和 SendMessage 描述

二、自定义窗体消息步骤(父子窗体传递消息、本窗体传递消息)

1.在全局头文件中 宏定义消息ID

2.在要响应动作的窗体类 头文件和源文件 声明和定义消息响应函数:

3.在源文件的消息映射添加自定义消息和响应函数的映射

4.消息发送

三、窗体的属性注意事项

四、拓展-项目窗体整体消息管理

一、PostMessage 和 SendMessage 描述

1.SendMessage‌ 是同步的,它会阻塞调用线程,直到目标窗口处理完消息并返回结果。这意味着调用线程会等待消息处理完成后再继续执行。

2.PostMessage‌ 是异步的,它将消息放入目标线程的消息队列后立即返回,不会等待消息处理完成。调用线程可以继续执行后续代码,而不关心消息是否被处理。‌

二、自定义窗体消息步骤(父子窗体传递消息、本窗体传递消息)

1.在全局头文件中 宏定义消息ID

/*

@基于 WM_USER 往上加, 其他自定义消息依次累加,自定义消息值不得相同/重复

*/

#define UM_MAINDLG_SHOW_DOMODAL WM_USER + 0x211 //

/********************************

@例子:

#define UM_MAINDLG_SHOW_DOMODAL WM_USER + 0x211

#define UM_MOUSE_RIGHT_KEY WM_USER + 0x211

*当上两个消息在同一个窗体的消息映射中:

.....

ON_MESSAGE(UM_MOUSE_RIGHT_KEY, &CPstParamDlg::OnSaveParam) //(1)

ON_MESSAGE(UM_MAINDLG_SHOW_DOMODAL, &CPstParamDlg::OnUmNotifyParent)

.....

UM_MAINDLG_SHOW_DOMODAL 消息会被 UM_MOUSE_RIGHT_KEY 捕获,导致 OnUmNotifyParent 没有响应

*******************************/

2.在要响应动作的窗体类 头文件和源文件 声明和定义消息响应函数:

//头文件.h 声明消息响应函数

afx_msg LRESULT OnUmShowDomodal(WPARAM wParam, LPARAM lParam);

//源文件 .cpp 定义消息响应函数

afx_msg LRESULT CMainDlg::OnUmShowDomodal(WPARAM wParam, LPARAM lParam)

{

int nType = (int)wParam; //解析发送过来的参数

switch (nType)

{

case 0:

{

break;

}

default:

break;

}

return 0;

}

3.在源文件的消息映射添加自定义消息和响应函数的映射

//源文件 .cpp

BEGIN_MESSAGE_MAP(CMainDlg, CDialogEx)

ON_WM_CTLCOLOR()

ON_WM_SHOWWINDOW()

ON_MESSAGE(UM_MOUSE_RIGHT_KEY, &CMainDlg::OnSaveParam) //会截获消息

//.

//.

ON_MESSAGE(UM_MAINDLG_SHOW_DOMODAL, &CMainDlg::OnUmShowDomodal) //增加自定义消息映射

END_MESSAGE_MAP()

4.消息发送

4.1 给本窗体自定义消息发送

void CMainDlg::SendMessageFunc()

{

*本窗体消息发送

PostMessage(UM_MAINDLG_SHOW_DOMODAL,0,0/*传送该值Type*/);

//::PostMessage(GetSafeWnd(),UM_MAINDLG_SHOW_DOMODAL,0,0/*传送该值Type*/);

//或

SendMessage(UM_MAINDLG_SHOW_DOMODAL,0,1/*传送该值Type*/);

//::SendMessage(GetSafeWnd(),UM_MAINDLG_SHOW_DOMODAL,0,0/*传送该值Type*/);

}

4.2 消息映射和消息响应函数在子窗体,父窗体通过 SendMessage 或 PostMessage 发送消息到子窗体:

//父窗体源文件 new 子窗体

std::vector m_vecChildDlg;

void CMainDlg::InitChildDlg()

{

m_vecChildDlg.push_back(new CChildDlg(......));

//....

//....

std::vector::iterator it = m_vecChildDlg.begin();

for( ; it != m_vecChildDlg.end(); it++)

{

(*it)->Create(IDD_DIALOG_CHILD,this);

(*it)->ShowWindow(SW_NORMAL);

}

}

//父窗体发送消息给子窗体

void CMainDlg::SendMessageToChild()

{

std::vector::iterator it = m_vecChildDlg.begin();

for( ; it != m_vecChildDlg.end(); it++)

{

/*

@发送消息 或用PostMessage

*/

(*it)->SendMessage(UM_NOTIFY_CHILD, NULL, 0);

}

}

/*

子窗体源文件接收并解析消息

ON_MESSAGE(UM_NOTIFY_CHILD, &CChildDlg::OnUmNotifyChild)

*/

afx_msg LRESULT CChildDlg::OnUmNotifyChild(WPARAM wParam, LPARAM lParam)

{

((CButton *)GetDlgItem(IDC_CHECK1))->SetCheck((int)lParam);

if (m_pnInitValue != nullptr)

{

*m_pnInitValue = (BOOL)lParam;

}

return 0;

}

4.3 消息映射以及消息响应函数在父窗体中,子窗体发送消息到父窗体:

//子窗体发送消息到上一层父窗体

void CChildDlg::OnBnClickedCheck1()

{

UpdateData(TRUE);

if (m_pnInitValue != nullptr)

{

*m_pnInitValue = m_nValue;

}

m_btnCheck.SetColor(RGB(255,255,255),m_colorEdit);

::SendMessage(GetParent()->GetSafeHwnd(), UM_NOTIFY_PARENT, (WPARAM)(static_cast(this)), (LPARAM)IsDlgButtonChecked(IDC_CHECK1));

}

/*

父窗体接收并解析消息

ON_MESSAGE(UM_NOTIFY_PARENT, &CMainDlg::OnUmNotifyParent)

*/

afx_msg LRESULT CMainDlg::OnUmNotifyParent(WPARAM wParam, LPARAM lParam)

{

CDlgParam *pParam = (CDlgParam *)wParam;

CString ss = pParam->GetParamName();

if (pParam->GetParamName() == _T("子窗体1"))

{

if ((bool)lParam)

{

//.......

}

}

return 0;

}

三、窗体的属性注意事项

1.以上步骤完成后,消息函数依旧没有响应,除了可以考虑消息可能被其他消息映射截获的异常,还可以查看窗体的 ' No Parent Notifly ' 窗体属性是否屏蔽了消息响应。

四、拓展-项目窗体整体消息管理

1.基于综上知识点,可以将项目里面的所有窗体消息集中管理,可以在需要的地方给对象窗体发送需要的消息数据等。思路如下:

1.1声明全局静态窗体消息管理类:

//Global.h

#include

#include

#define DlgMsgCtrl (WM_USER + 210) //自定义消息

class CInfoControl

{

private:

CInfoControl();

~CInfoControl();

static std::mutex m_mutex; //

static std::vector m_vecCWnd; //集中管理的窗体指针

public:

static void AddCwndInfo(HWND pWnd); //每一个窗体初始化 OnInitDialog() 的时候将窗体注册进去

static void SendInfo(CString strType, CString strMsg); //将消息向注册的窗体群发,每个窗体消息里面可以做自己的消息标志过滤;

};

1.2 窗体消息管理类实现:

#include "pch.h"

#include "Global.h"

#include

#include

CInfoControl::CInfoControl()

{

}

CInfoControl::~CInfoControl()

{

}

std::mutex CInfoControl::m_mutex;

std::vector CInfoControl::m_vecCWnd;

void CInfoControl::AddCwndInfo(HWND pWnd)

{

std::lock_guard lock(m_mutex);

if (pWnd != nullptr)

{

for (int i = 0; i < m_vecCWnd.size(); i++)

{

if (m_vecCWnd[i] == pWnd)

{

return;

}

}

m_vecCWnd.push_back(pWnd);

}

return;

}

void CInfoControl::SendInfo(CString strType,CString strMsg)

{

std::lock_guard lock(m_mutex);

for (int i = 0 ; i < m_vecCWnd.size() ; i++)

{

if (m_vecCWnd[i] != nullptr)

{

::SendMessage(m_vecCWnd[i],DlgMsgCtrl,(WPARAM)strType.GetBuffer(),(LPARAM)strMsg.GetBuffer());

}

}

return;

}

2.某一窗体的实现:

//.h 声明消息响应函数

afx_msg LRESULT InfoMsg(WPARAM wParam, LPARAM lParam);

//.cpp

//增加消息映射

ON_MESSAGE(DlgMsgCtrl,&CMFCApplication2Dlg::InfoMsg)

//增加响应函数实现

afx_msg LRESULT CMFCApplication2Dlg::InfoMsg(WPARAM wParam, LPARAM lParam)

{

CString strType = (TCHAR *)wParam;

CString strMsg = (TCHAR *)lParam;

//....消息过滤

//....消息处理

return 0;

}

//任意地方发送消息 群发消息

void CMFCApplication2Dlg::OnBnClickedButton1()

{

CInfoControl::SendInfo(_T("ERROR_SHOW"),_T("DLG_1::群发消息,需要的窗体做标志过滤"));

return;

}