引入
我接着上篇博客讲,如果没有构建项目的童鞋请移步到操作系统——MFC实现进程创建和通信1
用PostMessage实现通信请移步到操作系统——MFC实现进程创建和通信2
实现进程通信的方法有很多,这篇博客使用WM_COPYDATA消息完成进程间通信。
用WM_COPYDATA消息实现通信
通信原理
进程A发送WM_COPYDATA消息给进程B
SendMessage(接收窗口句柄, WM_COPYDATA, (WPARAM)发送窗口句柄, (LPARAM)©Data);
其中的copyData是要发送的数据,类型为COPYDATASTRUCT结构体:
typedef struct tagCOPYDATASTRUCT
{
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
dwData : Specifies up to 32 bits of data to be passed to the receiving application.
cbData : Specifies the size, in bytes, of the data pointed to by the lpData member.
lpData : Long pointer to data to be passed to the receiving application. This member can be NULL.
该消息只能由SendMessage()发送,而不能使用PostMessage()。因为系统必须管理用以传递数据的缓冲区的生命期,如果使用了PostMessage(),数据缓冲区会在接收方(线程)有机会处理该数据之前,就被系统清除和回收。
如果传入的接收窗口句柄无效或者当接收方进程意外终止时,SendMessage()会立即返回,发送方不会陷入一个无穷等待的状态中。
MainProcess中添加发送函数
在资源视图中双击Button进入到点击事件函数的处理中。
在处理函数中添加以下代码完成Copydata消息的发送。
void CMFCApplication1Dlg::OnBnClickedOk4()
{
LRESULT copyDataResult;
CString strDataToSend;//要传输的内容
GetDlgItemText(IDC_EDIT1, strDataToSend);//从控件获取内容
CWnd* pOtherWnd = CWnd::FindWindow(_T("#32770"), _T("ChildProcess"));//获取进程句柄
if (pOtherWnd)
{
COPYDATASTRUCT cpd;//可以传输到其他进程的结构体
cpd.cbData = 2 * strDataToSend.GetLength();//数据长度,注意乘2
cpd.lpData = strDataToSend.GetBuffer(); //数据指针
copyDataResult = pOtherWnd->SendMessage(WM_COPYDATA, (WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(), (LPARAM)&cpd);//发送
strDataToSend.ReleaseBuffer();//销毁
}
else
{
AfxMessageBox(_T("没有找到子进程"));
}
}
Copydata这个消息通过sendMessage方法发送给进程B后,进程A就不在拥有Copydata的句柄。
在ChildProcessDlg.cpp中添加发送函数
直接右键点击childProcess通过类向导添加COPYDATA消息处理函数(框架自动添加的,总比自己填一堆要好,框架会帮忙在头文件添加声明我们只用写定义方便很多)
最后点击添加处理程序就可以在ChildProcess实现文件中看到定义了,也可以直接点击编辑代码加上以下代码:
BOOL CChileProcessDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
if (pCopyDataStruct->cbData > 0)
{
char recvData[1024] = { 0 };
memcpy(recvData, (char*)pCopyDataStruct->lpData, pCopyDataStruct->cbData);
CString str;
str.Format(_T("%s"), recvData);
SetDlgItemText(IDC_EDIT1, str);
}
return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}
重新生成一下ChildProcess项目,编译运行
WM_COPYDATA消息是通过用户自定义一个结构体,然后进程A通过SendMessge方法将这个结构体发送给进程B从而实现进程通信的。
由于结构体最多也就那么大,所以Copydata不适合用来传输大型消息,接下来我会介绍大型消息传输常用的方法—内存共享和管道通信。
操作系统——MFC实现进程创建和通信4