在VC中用WM_COPYDATA在进程间发送数据
用WM_COPYDATA的前提:
1,知道接收消息进程的句柄。
2,接收消息进程重载了WM_COPYDATA消息映射,能对其做出反应(否则不是发送端自作多情了?)
看过前提,的出结论:在自己写的两个进程间用WM_COPYDATA再好不过。
下面CODE几行就说明了一切。
获得句柄的方法,最简单的方法就是使用FindWindow,找窗口类,或者名,如果你觉得这样不把握,那就利用SetProp个窗口做个记号....(不说这些,跑踢儿了都)
******************************************************************************************************
进程之间通讯的几种方法:
在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯。常用的方法有
使用内存映射文件
通过共享内存DLL共享内存
使用SendMessage向另一进程发送WM_COPYDATA消息
比起前两种的复杂实现来,WM_COPYDATA消息无疑是一种经济实惠的一中方法.
WM_COPYDATA 消息的主要目的是允许在进程间传递只读数据。Windows在通过WM_COPYDATA消息传递期间,不提供继承同步方式。SDK文档推荐用户使用SendMessage函数,接受方在数据拷贝完成前不返回,这样发送方就不可能删除和修改数据:
这个函数的原型及其要用到的结构如下:
SendMessage(hwnd,WM_COPYDATA,wParam,lParam);
其中,WM_COPYDATA对应的十六进制数为0x004A
wParam设置为包含数据的窗口的句柄。lParam指向一个COPYDATASTRUCT的结构:
typedef struct tagCOPYDATASTRUCT{
DWORD dwData;//用户定义数据
DWORD cbData;//数据大小
PVOID lpData;//指向数据的指针
}COPYDATASTRUCT;
该结构用来定义用户数据。
*************************************************************************
发送端代码:
1.字符串的发送
CString m_szdata;
m_szdata = _T("hello");
ShellExecute(NULL,NULL,"EditDlg.exe",NULL,NULL,SW_SHOW);
Sleep(100);
HWND hWnd = ::FindWindow(NULL,"EditDlg");
if(hWnd != NULL)
{
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
//cpd.dwData = 1; //标志发送字符串
//cpd.cbData = strlen("字符串")+1;
//cpd.lpData = "字符串";
//::SendMessage(hWnd,WM_COPYDATA,NULL,(LPARAM)&cpd);//发送!
cpd.dwData = 1; //标志发送CString类型
cpd.cbData = m_szdata.GetLength()+ 1;
cpd.lpData = (void*)m_szdata.GetBuffer(cpd.cbData);
::SendMessage(hWnd,WM_COPYDATA,NULL,(LPARAM)&cpd);//发送!
}
//还需要解决的是发送数组问题
CString strWindowTitle = _T("testcomm");
CString strDataToSend = _T("This is a message to send");
LRESULT copyDataResult;
CWnd *pOtherWnd = CWnd::FindWindow(NULL, strWindowTitle);
if (pOtherWnd)
{
COPYDATASTRUCT cpd;
cpd.dwData = 0;
cpd.cbData = strDataToSend.GetLength();
cpd.lpData = (void*)strDataToSend.GetBuffer(cpd.cbData);
copyDataResult = pOtherWnd->SendMessage(WM_COPYDATA,
(WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),
(LPARAM)&cpd);
strDataToSend.ReleaseBuffer();
// copyDataResult has value returned by other app
}
else
{
AfxMessageBox("Unable to find other app.");
}
OnOK();
2.数组的发送
void CMainFrame::OnMenuitem32773()
{
// TODO: Add your command handler code here
int BIT16Size = 64;
BIT16 int3array[64+1] ;
int3array[0] = BIT16Size;
for(int i=0; i<BIT16Size; i++)
{
int3array[i+1] = 0x14;
}
this->SendDataToBIT16EditDlg(int3array,BIT16Size+1);
}
SendDataToBIT16EditDlg为发送一个数组,数组中有1+N个数,第一个为数据大小N,其它为实际数据N个,它的定义如下:
void CMainFrame::SendDataToBIT16EditDlg(BIT16 BIT16DataArray[], int WholeSize)
{
HWND hWnd = ::FindWindow(NULL,"EditDlg"); //找到窗口
if(hWnd != NULL)
{
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = 2; // 标志为数组类型
cpd.cbData = sizeof(BIT16)*WholeSize;
cpd.lpData = (void *)BIT16DataArray;
::SendMessage(hWnd,WM_COPYDATA,NULL,(LPARAM)&cpd);//发送!
}
}
3.结构体的发送
//发送3,结构体,此处仅定义了2个整型变量
void CMainFrame::OnMenuitem32774()
{
typedef struct{
int temp_SizeofDataArray;
int temp_DataArray;
}DynamicArray;
DynamicArray StuArray;
StuArray.temp_SizeofDataArray = 3;
StuArray.temp_DataArray = 4;
HWND hWnd = ::FindWindow(NULL,"EditDlg");
if(hWnd != NULL)
{
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = 3; // 标志为DynamicArray类型
cpd.cbData = sizeof(StuArray);
cpd.lpData = &StuArray;
::SendMessage(hWnd,WM_COPYDATA,NULL,(LPARAM)&cpd);//发送!
}
}
接收端代码:
接收端重载ON_WM_COPYDATA消息映射函数,可用ClassWizard来添加.
//程序间传送数据,其它进程可以给本进程发送数据
BOOL CEditDlgDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
// TODO: Add your message handler code here and/or call default
using namespace std;
CString str;
typedef struct{
int temp_SizeofDataArray; //数组大小
int temp_DataArray; //十六进制数组
}DynamicArray;
int size,i;
switch (pCopyDataStruct->dwData)
{
case 1: // 接收到的是字符串或CString类型
AfxMessageBox((LPCSTR)(pCopyDataStruct->lpData));
break;
case 2: // 接收到的是数组类型
BIT16 *int3array;
int3array = (BIT16 *)(pCopyDataStruct->lpData); //放入数组
size = int3array[0].to_ulong(); //第一行为数组大小
m_edit16Binary.DataArray.clear();
for(i=1; i < size+1; i++)
{
m_edit16Binary.DataArray.push_back(int3array[i]);
}
m_edit16Binary.SizeofDataArray = size;
m_edit16Binary.Efficacy = m_edit16Binary.MakeEfficacy();
//更新编辑框,显示正确的效验和
m_edit16Binary.Init();
OnButtonEfficacy();
break;
case 3: //接收到的是结构体
DynamicArray *pstuArray;
pstuArray = (DynamicArray *)(pCopyDataStruct->lpData);
str.Format("%d",pstuArray->temp_SizeofDataArray);
AfxMessageBox(str);
str.Format("%d",pstuArray->temp_DataArray);
AfxMessageBox(str);
break;
default:
break;
}
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
头文件说明:
#include <bitset>
#include <vector>
using namespace std;
typedef bitset< 16 > BIT16;
******************************************************************************************************
进程通信还有其他一些手段,相对来说比较麻烦,但局限性要比WM_COPYDATA小。当然你也可以两端都注册一个消息来通信.
程序之间传递参数有多种实现方法:
1。发消息传递传递一个数值,使用wm_copydata结构可传递一组各种不同类型的参数。
2。如果是一对多个程序发消息(共享),须使用RegisterWindowMessage()注册消息标识符
3。使用共享文件传递大批量数据,用发消息的方法通知。
4。使用剪贴板,静态交换。
5。使用原子
6。DDE动态数据交换。