一、定义
Cwnd::SendMessage
函数用于向窗口发送消息。以下是 SendMessage
的基本用法示例:
LRESULT SendMessage(
UINT message, // 消息类型
WPARAM wParam, // 参数1
LPARAM lParam // 参数2
);
其中:
message
是要发送的消息类型,通常是一个预定义的 Windows 消息常量(例如,WM_CLOSE
、WM_COMMAND
等)或者自定义的消息类型。wParam
和lParam
是消息的参数,其具体含义取决于消息类型
二、SendMessage
特点
-
同步调用:
SendMessage
是一个同步函数,它会将消息发送到指定的窗口,并等待窗口的消息处理函数完成后才返回。这意味着它会阻塞当前线程,直到消息处理完成。这对于确保消息的有序处理非常有用。 -
线程内通信: 通常情况下,
SendMessage
用于在同一线程内的不同窗口之间进行消息传递,以确保消息的同步和有序处理。 -
消息参数:
wParam
和lParam
参数的具体含义取决于消息的类型,不同的消息有不同的参数。请查阅相关消息的文档以了解详细信息。 -
返回值:
SendMessage
的返回值通常包含有关消息处理结果的信息,其具体含义也取决于消息类型。通常,返回值是消息处理函数返回的结果。
需要注意的是,由于 SendMessage
是同步调用,如果在主 UI 线程中的某个窗口上使用它来发送消息,而消息处理函数执行耗时较长,可能会导致界面冻结。因此,要谨慎使用 SendMessage
,确保不会阻塞主 UI 线程。在某些情况下,可以考虑使用 PostMessage
来进行异步消息传递,以避免界面冻结。
三、同一进程中发送消息
实例
// 向窗口发送 WM_CLOSE 消息,请求关闭窗口
::SendMessage(hWnd, WM_CLOSE, 0, 0);
// 向窗口发送自定义消息,传递两个参数
UINT customMessage = WM_USER + 1; // 自定义消息,WM_USER 是一个用户自定义消息的基准值
WPARAM wParam = 42;
LPARAM lParam = 123;
::SendMessage(hWnd, customMessage, wParam, lParam);
传递两个字符串
void CAaaDlg::OnButton1()
{
char* p1 = "Willis";
char* p2 = "VCHelp";
SendMessage(WM_CURRENTINFO, (WPARAM)p1, (LPARAM)p2);
}
四、 不同进程发送消息传递字符串
问题
两个进程由于使用的是相互独立的两个虚拟内存空间,同一地址对不同的进程来说并不一定指向同一物理内存,内容也就不一定一样,因此不同进程无法通过传地址的方式传递字符串(但是同一进程下的不同线程是可以的)
解决办法
发送WM_COPYDATA消息在进程间传送数据,使用FindWindow找到窗口,然后发送WM_COPYDATA消息,字符串附加到COPYDATASTRUCT 结构体
实例
首先,创建两个 MFC 应用程序项目,一个作为发送方,另一个作为接收方。
发送方示例:
-
打开发送方的 MFC 应用程序项目。
-
在发送方的窗口类中,添加一个按钮用于触发消息发送,以及一个编辑框用于输入要发送的字符串。
- 在
CMySendAppDlg.cpp
中实现按钮的点击事件,以便发送字符串消息。
// MySendAppDlg.h
class CMySendAppDlg : public CDialogEx
{
public:
// ...
afx_msg void OnBnClickedSendButton();
private:
CEdit m_Edit;
// ...
};
// MySendAppDlg.cpp
void CMySendAppDlg::OnBnClickedSendButton()
{
CString strMessage;
m_Edit.GetWindowText(strMessage);
// 创建 COPYDATASTRUCT 结构并填充数据
COPYDATASTRUCT cds;
cds.dwData = 1; // 用户自定义的消息标识
cds.cbData = (DWORD)(strMessage.GetLength() + 1) * sizeof(TCHAR);
cds.lpData = (PVOID)(LPCTSTR)strMessage;
// 查找接收方窗口句柄,替换为接收方的窗口句柄
HWND hwndReceiver = ::FindWindow(NULL, _T("ReceiverApp Title"));
if (hwndReceiver)
{
// 发送消息
::SendMessage(hwndReceiver, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds);
}
else
{
AfxMessageBox(_T("接收方应用程序未找到!"));
}
}
接收方示例:
-
打开接收方的 MFC 应用程序项目。
-
在接收方的窗口类中,添加一个用于显示接收到的消息的编辑框。
- 在
CMyReceiveAppDlg.cpp
中添加一个消息映射以处理WM_COPYDATA
消息。
// MyReceiveAppDlg.h
class CMyReceiveAppDlg : public CDialogEx
{
public:
// ...
afx_msg LRESULT OnCopyData(WPARAM wParam, LPARAM lParam);
private:
CEdit m_Edit;
// ...
};
// MyReceiveAppDlg.cpp
BEGIN_MESSAGE_MAP(CMyReceiveAppDlg, CDialogEx)
// ...
ON_MESSAGE(WM_COPYDATA, OnCopyData)
// ...
END_MESSAGE_MAP()
LRESULT CMyReceiveAppDlg::OnCopyData(WPARAM wParam, LPARAM lParam)
{
COPYDATASTRUCT* pcds = (COPYDATASTRUCT*)lParam;
if (pcds)
{
CString strMessage((LPCTSTR)pcds->lpData);
m_Edit.SetWindowText(strMessage);
}
return 0;
}
在这个示例中,当发送方应用程序点击按钮发送消息时,接收方应用程序会通过 WM_COPYDATA
消息接收并显示接收到的消息。
确保在实际应用程序中使用正确的窗口标题(FindWindow
中的 "ReceiverApp Title" 和接收方应用程序的窗口标题)和消息标识符(dwData
中的 1 和 WM_COPYDATA
消息的处理部分)。此外,对于实际应用程序,还应该考虑错误处理和安全性。
SendMessage和PostMessage发送消息(不同进程传递字符串)_sendmessage发送字符串_紫松Win的博客-CSDN博客