注册用户自定义消息

2025-12-09 12:56:28

注册用户自定义消息

书籍:《Visual C++ 2017从入门到精通》的3.8.5 查找/替换对话框的使用

环境:visual studio 2022

内容:[例 3.14] 查找/替换对话框的使用

说明:以上内容大部分来自腾讯元宝。

在MFC中注册自定义消息需要遵循系统规范,确保消息的唯一性和正确性。以下是详细步骤及原理说明:

​​一、消息注册流程​​

​​1. 定义消息名称​​

消息名称需唯一,通常以项目前缀命名(如MYAPP_SHOW):

// 在公共头文件(如stdafx.h)中定义

#define WM_MY_CUSTOM_MESSAGE _T("MyApp_CustomMessage")

​​2. 注册消息​​

通过 RegisterWindowMessage 函数动态生成唯一消息ID:

// 在类初始化函数(如OnInitDialog)中注册

UINT m_nCustomMsg = RegisterWindowMessage(WM_MY_CUSTOM_MESSAGE);

if (m_nCustomMsg == 0) {

AfxMessageBox(_T("消息注册失败!"));

return FALSE;

}

​​返回值​​:成功时返回 0xC000~0xFFFF 之间的唯一ID,失败返回0。​​作用域​​:消息ID在注册它的进程中有效,跨进程需使用相同名称重新注册。

​​二、消息映射与处理​​

​​1. 声明消息处理函数​​

在类头文件中声明处理函数:

// MyDialog.h

class CMyDialog : public CDialogEx {

DECLARE_MESSAGE_MAP()

public:

afx_msg LRESULT OnCustomMessage(WPARAM wParam, LPARAM lParam);

};

​​2. 添加消息映射​​

在类实现文件的消息映射中绑定消息:

// MyDialog.cpp

BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)

ON_REGISTERED_MESSAGE(m_nCustomMsg, &CMyDialog::OnCustomMessage)

END_MESSAGE_MAP()

​​关键宏​​:ON_REGISTERED_MESSAGE 用于动态注册消息,ON_MESSAGE 用于预定义消息(如WM_USER+1)。

​​3. 实现消息处理函数​​

LRESULT CMyDialog::OnCustomMessage(WPARAM wParam, LPARAM lParam) {

CString strData = (LPCTSTR)lParam; // 假设传递字符串

AfxMessageBox(strData);

return 0;

}

​​三、发送消息​​

​​1. 同一进程内发送​​

通过窗口句柄直接发送:

// 发送端

CWnd* pWnd = FindWindow(NULL, _T("目标窗口标题"));

if (pWnd) {

::SendMessage(pWnd->m_hWnd, m_nCustomMsg, 0, (LPARAM)_T("Hello World"));

}

​​2. 跨进程发送​​

需确保目标进程已注册同名消息:

// 跨进程示例(需包含目标进程句柄)

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

if (hProcess) {

::SendMessage(hProcess, m_nCustomMsg, 0, (LPARAM)_T("跨进程消息"));

CloseHandle(hProcess);

}

​​四、注意事项​​

​​消息唯一性​​

使用 RegisterWindowMessage 保证系统唯一性,避免与其他消息冲突。跨进程通信时,需确保所有进程使用相同的消息名称。

​​线程安全​​

消息注册和发送需在主线程中完成,避免多线程竞争。

​​内存管理​​

若通过 lParam 传递指针,需确保接收方在消息处理前不释放内存。

​​调试技巧​​

使用 OutputDebugString 输出消息ID和内容,辅助调试。

​​五、完整示例​​

​​1. 注册与声明​​

// stdafx.h

#define WM_DATA_READY _T("DataReady")

// MyDialog.h

class CMyDialog : public CDialogEx {

DECLARE_MESSAGE_MAP()

public:

afx_msg LRESULT OnDataReady(WPARAM wParam, LPARAM lParam);

};

​​2. 注册与映射​​

// MyDialog.cpp

UINT CMyDialog::m_nDataMsg;

BOOL CMyDialog::OnInitDialog() {

CDialogEx::OnInitDialog();

m_nDataMsg = RegisterWindowMessage(WM_DATA_READY);

return TRUE;

}

BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)

ON_REGISTERED_MESSAGE(m_nDataMsg, &CMyDialog::OnDataReady)

END_MESSAGE_MAP()

LRESULT CMyDialog::OnDataReady(WPARAM wParam, LPARAM lParam) {

// 处理数据

return 0;

}

​​3. 发送消息​​

// 发送端代码

CMyDialog dlg;

dlg.DoModal();

::SendMessage(dlg.m_hWnd, dlg.m_nDataMsg, 0, (LPARAM)_T("数据已加载"));

​​六、扩展应用​​

​​自定义消息队列​​

通过 PostThreadMessage 将消息投递到指定线程的消息队列。

​​消息加密​​

对 wParam 和 lParam 进行加密传输,提升安全性。

​​多消息绑定​​

在消息映射中绑定多个处理函数:

ON_REGISTERED_MESSAGE(m_nMsg1, &CMyClass::OnMsg1)

ON_REGISTERED_MESSAGE(m_nMsg2, &CMyClass::OnMsg2)

通过以上步骤,可高效实现MFC消息的注册、发送与处理。若需跨模块通信,建议结合DLL注入或COM机制增强兼容性。

最新发表
友情链接

Copyright © 2022 日本世界杯_林高远世界杯 - edenyn.com All Rights Reserved.