使用WM_COPYDATA消息完成进程间通信



源地址:http://www.cnblogs.com/morewindows/archive/2011/09/23/2186294.html

发送WM_COPYDATA消息:

SendMessage(接收窗口句柄, WM_COPYDATA, (WPARAM)发送窗口句柄, (LPARAM)&CopyData);


其中的CopyData为COPYDATASTRUCT结构类型,该结构定义如下:

typedef struct tagCOPYDATASTRUCT {
	DWORD dwData;  // Specifies data to be passed to the receiving application.
	DWORD cbData;  //Specifies the size, in bytes, of the data pointed to by the lpData member.
 	PVOID lpData;    // Pointer to data to be passed to the receiving application. can be NULL.
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

注意:该消息只能由SendMessage()来发送,而不能使用PostMessage()。因为系统必须管理用以传递数据的缓冲区的生命期,如果使用了PostMessage(),数据缓冲区会在接收方(线程)有机会处理该数据之前,就被系统清除和回收。此外如果lpData指向一个带有指针或某一拥有虚函数的对象时,也要小心处理。

 

如果传入的句柄不是一个有效的窗口或当接收方进程意外终止时,SendMessage()会立即返回,因此发送方在这种情况下不会陷入一个无穷的等待状态中。

 

返回值问题,MSDN上说如果接收方处理了,返回TRUE,否则返回FALSE,但是本人在实验时,都是返回0(接收方已经处理)。

 

接收WM_COPYDATA消息:

只要用COPYDATASTRUCT *pCopyData = (COPYDATASTRUCT*)lParam;就可以了。接收方应认为这些数据是只读的。

 

由于发送方在接收方处理WM_COPYDATA消息完毕前都是处于等待中,所以接收方应当尽快处理WM_COPYDATA消息。

 

以一个简单的例子来说明如何使用WM_COPYDATA消息,有二个程序,一个用来发送表示当前时间信息的字符串,另一个接收数据后显示到编辑框中。例子中有几点要注意:

1.如何得到当前控制台窗口句柄?VS2008下可以直接使用HWND GetConsoleWindow(void);函数。

2.使用char *ctime(const time_t *timer);将一个time_t类型转化成一个字符串时,函数会在字符串末尾加下'\n',因为发送前要将这个'\n'去掉。

 

发送消息的程序代码(VS2008下编译通过):

#include <windows.h>
#include <time.h>
#include <conio.h>
#include <stdio.h>
int main()
{
       const char szDlgTitle[] = "RecvMessage";
 
       HWND hSendWindow = GetConsoleWindow ();
       if (hSendWindow == NULL)
              return -1;
       HWND hRecvWindow = FindWindow(NULL, szDlgTitle);
       if (hRecvWindow == NULL)
              return -1;
 
       char szSendBuf[100];
       time_t  timenow;
       COPYDATASTRUCT CopyData;
 
       for (int i = 0; i < 10; i++)
       {
              time(&timenow);
              sprintf(szSendBuf, "%s", ctime(&timenow));//注意,ctime()返回的字符串后面带了'\n'
              CopyData.dwData = i;
              CopyData.cbData = strlen(szSendBuf);
              szSendBuf[CopyData.cbData - 1] = '\0';
              CopyData.lpData = szSendBuf;
 
              SendMessage(hRecvWindow, WM_COPYDATA, (WPARAM)hSendWindow, (LPARAM)&CopyData);
              printf("%s\n", szSendBuf);
              Sleep(1000);
       }
       return 0;
}

 

接收消息程序代码(VC6.0下编译通过):

程序中的IDC_EDIT_RECVMESSAGE为编辑框的ID。


#include "stdafx.h"
#include "resource.h"
#include <stdio.h>
BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
      // TODO: Place code here.
       DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DlgProc);
       return 0;
}
BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
       const char szDlgTitle[] = "RecvMessage";
       static HWND s_hEditShowRecv;
 
       switch (message)
       {
       case WM_INITDIALOG:
              SetWindowText(hDlg, szDlgTitle);
              s_hEditShowRecv = GetDlgItem(hDlg, IDC_EDIT_RECVMESSAGE);
              return TRUE;
 
       case WM_COMMAND:
              switch (LOWORD(wParam))
              {
              case IDOK:
              case IDCANCEL:
                     EndDialog(hDlg, LOWORD(wParam));
                     return TRUE;
              }
              break;
 
       case WM_COPYDATA:
              {
                     COPYDATASTRUCT *pCopyData = (COPYDATASTRUCT*)lParam;
                     char szBuffer[300];
 
                     memset(szBuffer, 0, sizeof(szBuffer));
                     sprintf(szBuffer, "dwData:%d cbData:%d\r\nlpData:0x%08x = %s\r\n\r\n",
                            pCopyData->dwData, pCopyData->cbData,
                            (PVOID)pCopyData->lpData, (char*)pCopyData->lpData);
                     //在编辑框中追加数据
                     SendMessage(s_hEditShowRecv, EM_SETSEL, (WPARAM)-1, (LPARAM)-1); // (0, -1)表示全选, (-1,任意)表示全不选
                     SendMessage(s_hEditShowRecv, EM_REPLACESEL, FALSE, (LPARAM)szBuffer);
                     SendMessage(s_hEditShowRecv, EM_SCROLLCARET, 0, 0);
              }
              return TRUE;
       }
       return FALSE;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值