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 img_405b18b4b6584ae338e0f6ecaf736533.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 img_405b18b4b6584ae338e0f6ecaf736533.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

目录
相关文章
|
4天前
|
人工智能 测试技术 API
Windows用户必备:Postman v11详细安装指南与API测试入门教程(附官网下载
Postman是全球领先的API开发与测试工具,支持REST、SOAP、GraphQL等协议调试。2025年最新版v11新增AI智能生成测试用例、多环境变量同步等功能,适用于前后端分离开发、自动化测试、接口文档自动生成及团队协作共享API资源。本文详细介绍Postman的软件定位、核心功能、安装步骤、首次配置、基础使用及常见问题解答,帮助用户快速上手并高效利用该工具进行API开发与测试。
|
2月前
|
监控 搜索推荐 开发工具
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
186 2
2025年1月9日更新Windows操作系统个人使用-禁用掉一下一些不必要的服务-关闭占用资源的进程-禁用服务提升系统运行速度-让电脑不再卡顿-优雅草央千澈-长期更新
|
5月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
131 9
|
5月前
|
Java 关系型数据库 MySQL
java控制Windows进程,服务管理器项目
本文介绍了如何使用Java的`Runtime`和`Process`类来控制Windows进程,包括执行命令、读取进程输出和错误流以及等待进程完成,并提供了一个简单的服务管理器项目示例。
74 1
|
6月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
7月前
|
Java Windows
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
【Azure Developer】Windows中通过pslist命令查看到Java进程和线程信息,但为什么和代码中打印出来的进程号不一致呢?
|
7月前
|
Windows
Windows中如何查看被占用的端口、杀掉对应的进程
这篇文章介绍了在Windows系统中如何查看被占用的端口号以及如何杀掉占用端口的进程,包括使用命令提示符的`netstat -ano | findstr 端口号`命令查找进程PID,然后通过任务管理器或`taskkill /PID PID号`命令来结束进程。
Windows中如何查看被占用的端口、杀掉对应的进程
|
7月前
|
JavaScript Windows
NodeJs——如何获取Windows电脑指定应用进程信息
NodeJs——如何获取Windows电脑指定应用进程信息
173 0
|
7月前
|
Linux Windows
Windows查找监听端口对应的进程及其路径
Windows查找监听端口对应的进程及其路径
162 0
|
9月前
|
存储 数据安全/隐私保护 Windows
逆向学习Windows篇:进程句柄操作详解
逆向学习Windows篇:进程句柄操作详解
336 0

热门文章

最新文章