数据复制消息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消息的方法不合适,因为当数据传输过于频繁时,容易导致数据的丢失。

你可能感兴趣的:(function,null,Class,callback,structure)