《Windows核心编程》---数据复制消息WM_COPYDATA

WM_COPYDATA是一个非常特殊的消息,此消息可能携带一个比较大的消息参数,而其他消息都只能携带两个固定大小的参数(WPARAMLPARAM)。

WM_COPYDATA的两个参数如下:

wParam //发送或传递这个消息的窗口

lParam //指向包含要发送的数据的COPYDATASTRUCT结构的指针

在发送WM_COPYDATA消息时,WM_COPYDATAwParam参数应该赋值为发送此消息的窗口,而lParam消息参数指向一个COPYDATASTRUCT结构类型的变量:

typedef struct tagCOPYDATASTRUCT {

ULONG_PTR dwData; //可以是任意值

DWORD cbData; //lpData内存区域的字节数

PVOID lpData; //需要发送给目标窗口所在进程的数据

} COPYDATASTRUCT, *PCOPYDATASTRUCT;

在消息发送时,系统会将整个COPYDATASTRUCTlpData所指向的内容全部发送给目标进程。目标进程窗口在收到WM_COPYDATA后,可以从lParam参数中提取出数据。

数据发送端代码片段:

// ************ Globals ************

//

#define ASCEDISPLAY 1

typedef struct tagASCEREC //将用户输入的消息封装在这个结构中

{

wchar_t s1[80];

wchar_t s2[80];

DWORD n;

} ASCEREC;

COPYDATASTRUCT AsceCDS;

ASCEREC AsceRec;

HRESULT hResult;

BOOL CALLBACK InfoDlgProc( HWND, UINT, WPARAM, LPARAM );

// ************ Code fragment ****************

// Get data from user. InfoDlgProc stores the information in AsceRec.

//

DialogBox( ghInstance, TEXT("InfoDlg"), hWnd, (DLGPROC) InfoDlgProc );

//

// Copy data into structure to be passed via WM_COPYDATA.

// Also, we assume that truncation of the data is acceptable.

//

hResult = StringCbCopy(AsceRec.s1, sizeof(AsceRec.s1), szFirstName );

if (hResult != S_OK)

return False;

hResult = StringCbCopy(AsceRec.s2, sizeof(AsceRec.s2), szLastName );

if (hResult != S_OK)

return False;

AsceRec.n = nAge;

//

// Fill the COPYDATA structure

//

AsceCDS.dwData = ASCEDISPLAY; // function identifier

AsceCDS.cbData = sizeof( AsceRec ); // size of data

AsceCDS.lpData = &AsceRec; // data structure

//

// Call function, passing data in &AsceCDS

//此处假设接收进程具有一个类名为Disp32Class标题为"Hidden Window"窗口

hwDispatch = FindWindow( TEXT("Disp32Class"), TEXT("Hidden Window"));

if( hwDispatch != NULL )

SendMessage( hwDispatch, //接收消息的窗口的句柄

WM_COPYDATA, //要发送的消息

(WPARAM)(HWND) hWnd, //发送或传递这个消息的窗口

(LPARAM) (LPVOID) &AsceCDS ); //指向包含要发送的数据的

//COPYDATASTRUCT结构的指针

else

MessageBox( hWnd, TEXT("Can't send WM_COPYDATA"), TEXT("ASCEApp"), MB_OK );

数据接收端代码片段:

// ************ Globals ************

//

#define ASCEDISPLAY 1

typedef struct tagASCEREC

{

wchar_t s1[80];

wchar_t s2[80];

DWORD n;

} ASCEREC;

PCOPYDATASTRUCT pAsceCDS;

void WINAPI AsceDisplay( LPTSTR, LPTSTR, DWORD );

//

// ************ Code fragment ****************

//

case WM_COPYDATA:

pAsceCDS = (PCOPYDATASTRUCT) lParam;

switch( pAsceCDS->dwData )

{

case ASCEDISPLAY:

AsceDisplay( (LPTSTR) ((ASCEREC *)(pAsceCDS->lpData))->s1,

(LPTSTR) ((ASCEREC *)(pAsceCDS->lpData))->s2,

(DWORD) ((ASCEREC *)(pAsceCDS->lpData))->n );

}

break;

WM_COPYDATA消息的不足之处:

1)必须要有一个窗体来接收消息和数据(缺乏灵活性),数据在使用之前先得拷贝到一个映射文件(浪费资源);

2)只能是本机内的进程间通信;

3)必须让两个进程在启动后,相互知道主窗口的HWND(至少一方);

4)使用WM_COPYDATA消息时,只能用SendMessage()函数发送而不能使用PostMessage(),而这两个函数的区别是SendMessage()发出消息后不是立即返回,而是在接收方的消息响应函数处理完之后才返回,并能够得到返回结果,在此期间发送方程序将被阻塞,即SendMessage()函数后面的语句不能被继续执行;而PostMessage()函数在发出消息后将立即返回,且无法获得消息的执行结果。

由此可见,在交换数据量较大的情况下实现数据频繁而快速地交换时,使用WM_COPYDATA消息的方法不合适,因为当数据传输过于频繁时,容易导致数据的丢失。

你可能感兴趣的:(windows)