1. 概述
WM_COPYDATA是一种非常强大却鲜为人知的消息。当一个应用向另一个应用传送数据时,发送方只需使用调用SendMessage函数,参数是目的窗口的句柄、传递数据的起始地址、WM_COPYDATA消息。接收方只需像处理其它消息那样处理WM_COPY DATA消息,这样收发双方就实现了数据共享。
WM_COPYDATA是一种非常简单的方法,它在底层实际上是通过文件映射来实现的。它的缺点是灵活性不高,并且它只能用于Windows平台的单机环境下。
在发送消息的时候需要使用到的信息发送消息结构体为COPYDATASTRUCT,它的原型为
typedef struct tagCOPYDATASTRUCT {
ULONG_PTR dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
参数解释
dwData为32位的自定义数据
lpData
为指向数据的指针
cbData
lpData指针指向数据的大小(字节数)
定义好消息结构数据之后,需要的是要发送消息使用的函数为SendMessage(),它的函数原型为
LRESULT WINAPI SendMessage(
_In_ HWND hWnd,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
参数解释
hWnd:为接收进程的窗体句柄
Msg:WM_COPYDATA结构体
wParam:为发送进程的窗体句柄
lParam:为指向COPYDATASTRUCT数据结构的指针
这里需要注意的:传输的COPYDATA数据在发送后要避免被发送进程中的其他线程修改,其次要确保被传输的数据中没有包含接收进程无法访问的对象的指针或引用。比如:发送进程自身的HDC、HBITMAP之类的东西,它们对于接收进程来说是无效的。
在发送消息的时候,目标窗口的窗口句柄是通过FindWindow()函数实现的,具体的使用参考这篇博客。
2. 实现代码
2.1 发送端
添加发送按键的消息响应函数
//添加OnCopyData消息响应函数
BOOL CWM_COPYDATA_SendDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (pCopyDataStruct->cbData > 0) //如果有数据
{
LPTSTR kk = (LPTSTR)pCopyDataStruct->lpData;
CString str_temp = kk;
str_temp.Left(pCopyDataStruct->cbData/2);
CString str;
GetDlgItemText(IDC_EDIT_MsgHis, str);
str += _T("\r\n");
str += str_temp;
SetDlgItemText(IDC_EDIT_MsgHis, str);
}
return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}
添加WM_COPYDATA消息响应函数
//发送消息
void CWM_COPYDATA_SendDlg::OnBnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT_Msg, str);
if (str.GetLength() <= 0) return;
HWND receiveWindow = ::FindWindow(NULL, _T("WM_COPYDATA_Receive"));
if (receiveWindow == NULL)
{
MessageBox(_T("send 没有找到目标窗口"));
return;
}
COPYDATASTRUCT copyData = { 0 };
copyData.lpData = str.GetBuffer();
copyData.cbData = str.GetLength()*2;
//发送OnCopyData消息
::SendMessage(receiveWindow, WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)©Data);
}
2.2 接收端
添加发送按键的消息响应函数
void CWM_COPYDATA_ReceiveDlg::OnBnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码
CString str;
GetDlgItemText(IDC_EDIT_Msg, str);
if (str.GetLength() <= 0) return;
HWND receiveWindow = ::FindWindow(NULL, _T("WM_COPYDATA_Send"));
if (receiveWindow == NULL)
{
MessageBox(_T("receive 没有找到目标窗口"));
return;
}
COPYDATASTRUCT copyData = { 0 };
copyData.lpData = str.GetBuffer();
copyData.cbData = str.GetLength()*2;
//发送OnCopyData消息
::SendMessage(receiveWindow, WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)©Data);
}
添加WM_COPYDATA消息响应函数
BOOL CWM_COPYDATA_ReceiveDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (pCopyDataStruct->cbData > 0) //如果有数据
{
LPTSTR kk = (LPTSTR)pCopyDataStruct->lpData;
CString str_temp = kk;
str_temp.Left(pCopyDataStruct->cbData/2);
CString str;
GetDlgItemText(IDC_EDIT_MsgHis, str);
str += _T("\r\n");
str += str_temp;
SetDlgItemText(IDC_EDIT_MsgHis, str);
}
return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}
示例代码下载

本文介绍了Windows进程通信中的一种常见方法——WM_COPYDATA消息。通过WM_COPYDATA,应用程序可以方便地向其他应用传递数据。尽管底层原理基于文件映射,但其灵活性有限,仅适用于Windows平台的单机环境。发送端和接收端的实现涉及COPYDATASTRUCT结构体和SendMessage函数的使用,需注意数据保护和避免发送无效对象的指针。
5543

被折叠的 条评论
为什么被折叠?



