發送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;
}