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

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

typedef struct tagCOPYDATASTRUCT {

    ULONG_PTR dwData;

    DWORD     cbData;

    PVOID     lpData;

} COPYDATASTRUCT, *PCOPYDATASTRUCT;

dwData可以是任意值,lpData是需要发送给目录窗口所在进程的数据,cbData字符指定了lpData内存区域的字节数,也就是需要发送给目标进程的lpData所指向的数据的大小。

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

1、一个例子

数据发送端


23、Windows API 进程间通信,数据复制消息(WM_COPYDATA)_数据23、Windows API 进程间通信,数据复制消息(WM_COPYDATA)_#include_02通过WM_COPYDATA进程间通信-发送端


通过WM_COPYDATA进程间通信

**************************************/

/* 头文件 */

#include <windows.h>

#include <commctrl.h>

#include "resource.h"

/* 全局变量 */

HINSTANCE hinst;

HWND hwnd, hwndEdit;

LPSTR lpszCopy = "you can input any text\n then click \'Send\' Item at Menu";

/* 函数声明 */

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);

LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);


/* ************************************

* WinMain

**************************************/

int WINAPI WinMain(

HINSTANCE hinstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

MSG msg;

WNDCLASSEX wcx;


hinst = hinstance; // 保存应用程序实例


// 填充WNDCLASSEX

wcx.cbSize = sizeof(wcx);

wcx.style = CS_HREDRAW | CS_VREDRAW;

wcx.lpfnWndProc = MainWndProc; // 消息处理函数

wcx.cbClsExtra = 0;

wcx.cbWndExtra = 0;

wcx.hInstance = hinstance;

wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wcx.hCursor = LoadCursor(NULL, IDC_ARROW);

wcx.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH);

wcx.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_COMMAND); // 菜单

wcx.lpszClassName = "copydata"; // 窗口类名

wcx.hIconSm = NULL;

// 注册窗口类

if(RegisterClassEx(&wcx) == 0)

{

return 0;

}

// 创建窗口

hwnd = CreateWindow(

"copydata",

"Sample",

WS_TILEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT, 500, 400,

(HWND) NULL,

(HMENU) NULL,

hinstance,

(LPVOID) NULL);

if (!hwnd)

return 0;


// 显示、刷新窗口

ShowWindow(hwnd, nCmdShow);

UpdateWindow(hwnd);

// 消息循环


BOOL fGotMessage;

while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

UNREFERENCED_PARAMETER(lpCmdLine);

}


/* ************************************

* 消息处理函数

**************************************/

LONG APIENTRY MainWndProc(HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

switch (message)

{

case WM_CREATE:

{

// 在主窗口创建时,创建一个EDIT控件,用于编辑需要复制的内容

RECT rectMain;

GetClientRect(hwnd,&rectMain);

hwndEdit = CreateWindow("EDIT",

NULL,

WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |

ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,

0., 0, rectMain.right, rectMain.bottom,

hwnd, NULL,

(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),

NULL);

if(hwndEdit == NULL)

{

MessageBox(hwnd, "Create Window Error","ERROR",MB_OK);

ExitProcess(0);

}

// 设置EDIT控件的内容

SendMessage(hwndEdit, WM_SETTEXT, 0, (LPARAM) lpszCopy);

break;

}

case WM_COMMAND: // 菜单输入

{

// 如果通过菜单点击“send”按钮

if (LOWORD(wParam) == ID_COMMAND_SEND)

{

// 获取EDIT控件中的文本

DWORD dwTextLenth = GetWindowTextLength(hwndEdit);

LPSTR szText = (LPSTR)HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,dwTextLenth);

GetWindowText(hwndEdit,szText,dwTextLenth);

// 构造 COPYDATASTRUCT

COPYDATASTRUCT cds;

HWND hwnd2 = FindWindow("copydata2","RECV COPY DATA");

if(hwnd2 == NULL)

{

MessageBox(hwnd,"can not find window 2","ERROR",MB_OK);

break;

}

cds.dwData = 0x12345678; // 自定义的数据

cds.cbData = dwTextLenth; // lpData的长度

cds.lpData = szText; // 需要复制的数据

// 发送消息,COPYDATASTRUCT结构的指针做为lParam

SendMessage(

hwnd2, // 目的窗口

(UINT) WM_COPYDATA, // 消息 ID

(WPARAM) hwnd, // wParam,源窗口句柄

(LPARAM) &cds // lParam,COPYDATASTRUCT

);

// 释放内存

HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,szText);

}

break;

}

case WM_DESTROY: // 退出

PostQuitMessage(0);

return 0;


default: // 其他消息的处理

return DefWindowProc(hwnd, message, wParam, lParam);

}

return 0;

}


数据接收端


23、Windows API 进程间通信,数据复制消息(WM_COPYDATA)_数据23、Windows API 进程间通信,数据复制消息(WM_COPYDATA)_#include_02通过WM_COPYDATA进程间通信-接收端


通过WM_COPYDATA进程间通信

**************************************/

/* 头文件 */

#include <windows.h>

#include <commctrl.h>

/* 全局变量 */

HINSTANCE hinst;

HWND hwnd,hwndEdit;

/* 函数声明 */

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);

LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);


/* ************************************

* void main()

* 功能 进程间mailslot通信客户端

**************************************/

int WINAPI WinMain(

HINSTANCE hinstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

MSG msg;

WNDCLASSEX wcx;

// 填充WNDCLASSEX

wcx.cbSize = sizeof(wcx);

wcx.style = CS_HREDRAW | CS_VREDRAW;

wcx.lpfnWndProc = MainWndProc;

wcx.cbClsExtra = 0;

wcx.cbWndExtra = 0;

wcx.hInstance = hinstance;

wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);

wcx.hCursor = LoadCursor(NULL, IDC_ARROW);

wcx.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH);

wcx.lpszMenuName = NULL;

wcx.lpszClassName = "copydata2";

wcx.hIconSm = NULL;

// 注册窗口类

if(RegisterClassEx(&wcx) == 0)

{

return 0;

}

// 创建窗口

hwnd = CreateWindow(

"copydata2",

"RECV COPY DATA",

WS_TILEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT, 500, 400,

(HWND) NULL, (HMENU) NULL, hinstance, (LPVOID) NULL

);


if (!hwnd)

return 0;

// 显示刷新窗口

ShowWindow(hwnd, nCmdShow);

UpdateWindow(hwnd);

// 消息

BOOL fGotMessage;

while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

UNREFERENCED_PARAMETER(lpCmdLine);

return 0;

}


// 消息处理函数

LONG APIENTRY MainWndProc(HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

switch (message)

{

case WM_CREATE:

{

// 创建主窗口时,创建一个EDIT控件

RECT rectMain;

GetClientRect(hwnd,&rectMain);

hwndEdit = CreateWindow("EDIT",

NULL,

WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_BORDER |

ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,

0., 0, rectMain.right, rectMain.bottom,

hwnd,

NULL,

(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),

NULL);

if(hwndEdit == NULL)

{

MessageBox(hwnd, "Create Window Error","ERROR",MB_OK);

ExitProcess(0);

}

break;

case WM_COPYDATA:

{

// 当收到WM_COPYDATA消息时,从lParam中提取出

// COPYDATASTRUCT

PCOPYDATASTRUCT lpcds = (PCOPYDATASTRUCT)lParam;

// 将复制的数据在界面上显示

SetWindowText(hwndEdit,(LPSTR)lpcds->lpData);

break;

}


case WM_DESTROY: // 退出

PostQuitMessage(0);

return 0;


default: // 其他消息处理

break;

}

}

return DefWindowProc(hwnd, message, wParam, lParam);

}


Interprocess Communications[2]

参考