进程的通信 - WM_COPYDATA

news2024/10/7 18:27:52

在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯。其中使用SendMessage向另一进程发送WM_COPYDATA消息是一种比较经济实惠的方法。

WM_COPYDATA通信需要将传递的消息封装在COPYDATASTRUCT结构体中,在SendMessage消息传递函数时作为lParam参数传递

COPYDATASTRUCT的结构如下:

typedef struct tagCOPYDATASTRUCT {
  ULONG_PTR dwData;
  DWORD     cbData;
  PVOID     lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
  • 参数dwData

为自定义数据,按照自己习惯设置就好,不影响对象的传输;

  • 参数cbData

表示传递数据的大小(以字节为单位

  • 参数PVOID

表示传递的数据,是一个void*类型 

使用WM_COPYDATA时要用SendMessage而不能使用PostMessage,因为SendMessage是阻塞的,会等待消息响应窗体处理消息完毕后再返回;而PostMessage是异步的,这样就可能会导致当消息响应窗体接收到WM_COPYDATA的时候,COPYDATASTRUCT对象已经被析构了,导致访问数据发生异常。

LRESULT SendMessage(
  [in] HWND   hWnd,
  [in] UINT   Msg,
  [in] WPARAM wParam,
  [in] LPARAM lParam
);
  • 参数hWnd

表示接收消息的窗体句柄

  • 参数Msg

指定附加的消息特定信息。在WM_COPYDATA进程通信中这个参数设置成WM_COPYDATA

  • 参数wParam

指定附加消息的特定信息。在WM_COPYDATA通信中这个参数设置为当前窗体的句柄

可以通过AfxGetApp()->m_pMainWnd获得,但需要强转成WPARAM

  • 参数lParam

指定附加消息的特定信息。在WM_COPYDATA通信中这个参数设置为COPYDATASTRUCT结构体,也需要强转成lParam

使用WM_COPYDATA进行进程间的通信需要提前获得另一个进程的窗体句柄。虽然spy++工具可以每次查到窗体的句柄,但是进程每次运行后句柄可能会改变,因此我们要先获得窗体的名称,再通过FindWindow函数获得窗体句柄

strWindowTitle是窗体的名称 

HWND FindWindowW(
  [in, optional] LPCWSTR lpClassName,
  [in, optional] LPCWSTR lpWindowName
);
  • 参数lpClassName

一般设置为NULL

  • 参数lpWindowName

表示窗口的名称 

发送数据端 

返回值

函数成功,返回窗口的句柄

函数失败,返回NULL

在判断函数返回值时,不仅要判断返回的句柄是否为空,还需要判断句柄标识的是否是现有的窗口

通过调用IsWindow函数判断长提是否还存在

BOOL IsWindow(
  [in, optional] HWND hWnd
);
  • 参数hWnd

表示窗口的句柄

返回值

如果窗口句柄标识现有窗口,则返回值非零

如果窗口句柄未标识现有窗口,则返回零 

接收端

接收端通过消息响应函数来接收数据

带xxxDlg文件中添加WM_COPYDATA消息响应函数

f667c983b13a40fe8acfc48d5831f73a.png

 当有消息发送过来时就会响应这个函数,

BOOL CWMCOPYDATADlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}

通过解析参数COPYDATASTRUCT* pCopyDataStruct就可以获得发送过来的数据了

需要注意的是

  1. 使用WM_COPYDATA时要用SendMessage而不能使用PostMessage,因为SendMessage是阻塞的,会等待消息响应窗体处理消息完毕后再返回;而PostMessage是异步的,这样就可能会导致当消息响应窗体接收到WM_COPYDATA的时候,COPYDATASTRUCT对象已经被析构了,导致访问数据发生异常。
  2. COPYDATA结构体的实质依然是共享内存,区别是这一片特殊的共享内存由操作系统管理而不用用户手动申请管理。
  3. WM_COPYDATA适合小数据量的进程间通信,大数据量可能造成内存问题,以及界面卡死,因为消息的发送形式是同步的。

Demo示例:

8f8d95b3a5a14d93811fe951cfe2c65c.png

374f1656e6ab44659da4532bea29dc9b.png

新建两个基于对话框的MFC应用,将其中一个窗体名称定为“MFCRecv”,当点击第二个应用的发送按钮后,会向第一个应用发送一段数据,第一个应用会将消息通过消息框显示出来 。

发送端:

CString strWindowTitle = _T("MFCRecv");
HWND hRecvWnd = ::FindWindow(NULL, strWindowTitle.GetBuffer(0));

CString strDataToSend = _T("Hello,这是霸道小明");

if (hRecvWnd != NULL && ::IsWindow(hRecvWnd)) {
	//如果不是空,并且是一个窗口
		
	//数据的封装
	COPYDATASTRUCT cpd;
	cpd.dwData = 0;//要传递给应用程序的数据
	cpd.cbData = strDataToSend.GetLength() * sizeof(TCHAR);//传递数据的大小
	cpd.lpData = (PVOID)strDataToSend.GetBuffer(0);
	//AfxGetApp函数可以
	::SendMessage(hRecvWnd, WM_COPYDATA, (WPARAM)(AfxGetApp()->m_pMainWnd), (LPARAM)&cpd);
}
strDataToSend.ReleaseBuffer();

接收端:

//消息响应函数
BOOL CWMCOPYDATADlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	//窗口接收到消息,就会响应这个函数
	//解析数据
	LPCTSTR szText = (LPCTSTR)(pCopyDataStruct->lpData);
	DWORD dwLength = (DWORD)pCopyDataStruct->cbData;
	TCHAR szRecvText[1024] = { 0 };
	memcpy(szRecvText, szText, dwLength);
	MessageBox(szRecvText, _T("收到消息"), MB_OK);
	return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}

运行结果:

11f8ab557e2048cea59d71e2d8f41ad8.gif 

右端进程点击发送,左端继承就会将接收到的数据显示出来,此时右端继承会进入阻塞状态,直到左边进程对消息做出处理。 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/25159.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]java毕业设计校园超市进销存管理系统

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

基于PETALINUX的以太网调试

1、建立工程 2、编译工程,导出xsa文件 3、建立petalinux工程 4、生成boot和image.ub文件,将文件复制到系统为fat32的sd卡中。 5、插上串口,插上网线 6、vm中需要桥接网络,有正确的IP地址 7、通过串口,配置板卡的以太…

前端面试题(JS部分)

目录一, 数据类型1,什么是引用类型,值类型?2,哪些值类型3,哪些引用类型4,判断数据类型5,typeof判断6,instanceof7,construtor二,浅拷贝 / 深拷贝1…

好物推荐:文字转语音朗读软件哪个好?

不知道大家有没有像我一样的,对“语音播放”、“语音朗读”是又爱又恨的。有时工作繁忙,而同事或客户发来语音资料需要整理时,就会很烦躁,因为语音的整理起来比文字的繁琐一些。而像有时在家休息,还得看一些资料时&…

亚马逊鲲鹏系统之亚马逊买家号养号时需要注意哪些?

经常做亚马逊测评的朋友应该都清楚,亚马逊买家号养号是很有必要的,如果一个新买家号没有养过号就进行刷单测评,那么是很容易就死号了的。但是想要养好号也不是那么容易的,需要注意好多问题。 第一:养号的重点是号&…

Linux 软连接与硬链接

文件链接概念介绍: 软连接文件: 概念介绍:用于存放指向源文件的路径信息(文件快捷方式) 应用场景:对于要操作文件数据提供方便 硬链接介绍 硬链接不能跨分区创建 补充: 1.目录硬链接数代…

k8s-List机制及resourceVersion语义

kube-apiserver 核心职责 提供Restful API;代理集群组件,如dashboard、流式日志、kubectl exec 会话;缓存全量的etcd 数据且无状态服务可水平扩展。 kube-List操作 绝大部分情况下,kube-apiserver 都会直接从本地缓存提供服务&…

MybatisX插件 逆向工程

MybatisX插件 逆向工程 目录MybatisX插件 逆向工程安装插件使用插件安装插件 File->Settings->Plugins 使用插件 点击DataSource->点击“” 点击DataSource->点击MySQL 驱动选择MySQL for 5.1 输入主机IP、端口号、数据库的用户名和密码->点击Test Connec…

浅谈系统架构设计-从架构设计原理、架构设计原则、架构设计方法展开

我们工作中一直强调要做架构设计、系分,最近前端同学在追求前端质量提升的时候,也在进行架构设计、前端系分的推广,那到底什么是架构设计和系分?该怎么做架构设计和系分?本文尝试对架构设计进行全面的介绍和分享&#…

【机器学习】SVM入门-硬间隔模型

本站原创文章,转载请说明来自《老饼讲解-机器学习》ml.bbbdata.com 目录 一. SVM的目标和思想 1.1 SVM硬间隔模型的原始目的 1.2 SVM的直接目标 1.3 什么是支持向量 二. SVM的支持平面的表示方式 2.1 支持面表示方式的初步思路 2.2 初步思路的缺陷与改进 2…

基于Vue+ElementUI+MySQL+Express的学生管理系统(2)

2.搭建Express Web服务器 1.在E:\vue\shiyan9路径下创建score-server的文件夹放置Express Web服务器的相关文件。 图3 初始化package.json的信息 2.用Vscode打开score-server。并创建如图4所示的项目结构图。 以下目录中的文件依次为: 考试信息增删改查的接口。…

【BP回归预测】改进的鲸鱼算法优化BP神经网络回归预测(多输入单输出)【含Matlab源码 2184期】

⛄一、鲸鱼算法优化BP神经网络简介 1 鲸鱼优化算法(Whale Optimization Algorithm,WOA)简介 鲸鱼优化算法(WOA),该算法模拟了座头鲸的社会行为,并引入了气泡网狩猎策略。 1.1 灵感 鲸鱼被认为是世界上最大的哺乳动物…

DBCO-mPEG,5 kDa,二苯并环辛炔-MPEG, 5 KDA白色结晶状

●外观以及性质: DBCO-mPEG,5 kDa白色结晶状,其的分子量有多种,10kDa,20kDa,30kDa等一系列的。DBCO活化的聚乙二醇化试剂通过无铜“点击化学”反应与叠氮化物反应,形成稳定的三唑,不需要铜催化剂…

evpp mingw64编译过程

evpp是奇虎360的基于libevent的网络通讯库,源代码不错: https://github.com/Qihoo360/evpp/blob/master/readme_cn.md 它提供vs的编译结构,我用的是mingw64cmake,使用gnu12,把修改过程分享给大家。 步骤1. 修改CMake…

软考中级系统集成项目管理工程师自学好不好过?

可以试试,中级系统集成算是比较好考的一科目,每天的通过率都有30%的!是软考中通过率比较高的。 至于是否自学,有时间有精力就可以自学,在校生一般学习时间多,可以各个渠道搜集信息资料,可以自学…

高分子PEG点击试剂DBCO-PEG20K-OMe,二苯并环辛炔-PEG20K-甲基

DBCO-PEG20K-OMe​产品描述: DBCO-PEG20K-OMe属于高分子PEG点击试剂,DBCO 试剂是一类点击化学标记试剂,含有非常活泼的 DBCO((二苯并环辛炔)基团,​DBCO 试剂可以通过无铜点击化学与叠氮化物标…

vscode连接远程服务器进行cmake调试

一、cmake安装 cmake cmake-3.17.4.tar.gz : https://cmake.org/files/v3.17/cmake-3.17.4.tar.gz sudo apt-get install libssl-dev tar xvf cmake-3.17.4.tar.gz cd cmake-3.17.4 ./configure --prefix/usr make -j18 && sudo make install测试 二、配置 准备两…

如何找回删除的文件?数据恢复,看这几个方法

如果您的电脑出现了问题,或者是因为使用不当而删除了一些文件,那么您需要了解一下如何找回删除的文件。想要清理电脑文件数据,很多人会将其直接删除。其实这种做法是不可取的,因为这种做法可能会造成损失。如何找到已经删除的文件…

怎么把开源项目放到自己的github,gitee,gitea上

一、创建仓库(大部分可以不填) 二、删除.git文件夹 三、执行初始化命令(初始出.git文件夹) 在本地项目下执行命令 git init 四、与远程仓库建立关系 git remote add origin ssh://gitxx.xx.xx.xx:61022/shengbaitong/inst_ops…

IOC和DI入门案例

IOC案例 创建BookDao接口、BookDaoImpl类和BookService接口、BookServiceImpl类 1.BookDao package dao;public interface BookDao {public void save(); }2.BookDaoImpl类 package dao;public class BookDaoImpl implements BookDao{public void save(){System.out.printl…