开发者社区> hopegrace> 正文

23、Windows API 进程间通信,数据复制消息(WM_COPYDATA)

简介:     WM_COPYDATA是一个非常特殊的消息,此消息可能携带一个比较大的消息参数,而其他消息都只能携带两个固定大小的参数(WPARAM和LPARAM)。 在发送WM_COPYDATA消息时,WM_COPYDATA的wParam参数应该赋值为发送此消息的窗口,而lParam消息参数指向一个COPYDATASTRUCT结构类型的变量。
+关注继续查看

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

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

typedef struct tagCOPYDATASTRUCT {

    ULONG_PTR dwData;

    DWORD     cbData;

    PVOID     lpData;

} COPYDATASTRUCT, *PCOPYDATASTRUCT;

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

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

1、一个例子

数据发送端

img_1c53668bcee393edac0d7b3b3daff1ae.gif通过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;
}

数据接收端

img_1c53668bcee393edac0d7b3b3daff1ae.gif通过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]

参考

[1] 精通Windows API 函数、接口、编程实例

[2] http://msdn.microsoft.com/en-us/library/ms648710%28VS.85%29.aspx

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Qt实用技巧:Qt中添加对windows api的支持,显示/隐藏任务栏和桌面(解决无法找到windows api)
Qt实用技巧:Qt中添加对windows api的支持,显示/隐藏任务栏和桌面(解决无法找到windows api)
508 0
如何在Windows系统上使用Object Detection API训练自己的数据?
之前写了一篇如何在windows系统上安装Tensorflow Object Detection API?(点击跳转) 然后就想着把数据集换成自己的数据集进行训练得到自己的目标检测模型。动手之前先学习了一波别人是如何实现的,看了大多数教程都有一个小问题:用VOC2012数据集进行训练当做用自己的数据集。 然而,初心想看的是自己的数据集啊!于是就自己来撸一篇教程,方便自己也给别人一些参考吧~
145 0
如何在windows系统上安装Tensorflow Object Detection API?
都说Linux是最适合程序员使用的操作系统,这话还真不假。 之前一直在云服务器上跑代码,近期接手了师兄的台式机(GTX 1050),虽然配置很渣,但想在本地玩玩看,于是乎先安装一波Tensorflow Object Detection API。 之前云服上配置的时候十分顺利,可是到了windows下很容易进坑,这里简单整理下踩坑后的总结。
281 0
windows 本地测试spark streaming + kafka direct api
windows 本地测试spark streaming + kafka direct api 卡在如下信息出: “Kafka scala consumer marked as dead for group” 1.环境: kafka server为集群,连接时使用的是hostname:9092方法去连接,程序也不报错, 就是卡在上面的信息出,没有输出。
1496 0
WindowsAPI每日一练(2) 使用应用程序句柄
WindowsAPI每日一练系列 :https://www.cnblogs.com/LexMoon/category/1246238.html   WindowsAPI每日一练(1) WinMain  WindowsAPI每日一练(2) 使用应用程序句柄   从上面这段程序就可以看到,_tWinMain是应用程序的入口函数,这里是使用它的宏,定义在tchar.
1621 0
WindowsAPI每日一练(1) MessageBoxA
WindowsAPI每日一练系列 :https://www.cnblogs.com/LexMoon/category/1246238.html  WindowsAPI每日一练(1) WinMain 要跟计算机进行交互,就需要计算机显示信息给人看到,或者发出声音给人听到,然后人看到或听到相应的信息后,再输入其它信息给计算机,这样就可以让计算机进行数据处理,把结果显示给我们。
5577 0
+关注
hopegrace
文章
问答
视频
文章排行榜
最热
最新
相关电子书
更多
ECS运维指南之Windows系统诊断
立即下载
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
相关实验场景
更多