进程的通信 - WM_COPYDATA

这篇具有很好参考价值的文章主要介绍了进程的通信 - WM_COPYDATA。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在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消息响应函数

进程的通信 - WM_COPYDATA

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

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示例:

进程的通信 - WM_COPYDATA

进程的通信 - WM_COPYDATA

新建两个基于对话框的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);
}

运行结果:

进程的通信 - WM_COPYDATA 

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

 文章来源地址https://www.toymoban.com/news/detail-427460.html

 

到了这里,关于进程的通信 - WM_COPYDATA的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何设计WIndows系统下的单例进程程序?

    为了设计一个Windows系统下的单例进程程序,你可以遵循以下步骤: 首先,确定你的应用程序只能运行一个实例。这可以通过使用互斥量(Mutex)来实现。互斥量是一种同步对象,用于控制对共享资源的独占访问。 在应用程序的启动代码中,创建一个命名的互斥量对象。命名

    2024年01月22日
    浏览(48)
  • windows驱动开发7:应用程序和驱动程序的通信

    一、基础介绍 1.1 设备与驱动的关系 设备由驱动去创建,访问一个设备,是首先得访问驱动。如果驱动在卸载的时候没有删除符号,r3下也是不能去访问设备的。 驱动程序和系统其他组件之间的交互是通过给设备发送或者接受发给设备的请求来交互的。换句话说,一个没有任

    2023年04月08日
    浏览(51)
  • WM8978 —— 带扬声器驱动程序的立体声编解码器(2)

    接前一篇文章:WM8978 —— 带扬声器驱动程序的立体声编解码器(1) 引脚(PIN) 名称(NAME) 类型(TYPE) 描述(DESCRIPTION) 1 LIP 模拟输入 左麦克风前置放大器正极输入 2 LIN 模拟输入 左麦克风前置放大器负极输入 3 L2/GPIO2 模拟输入 左声道线路输入 / 辅助麦克风前置放大器正

    2024年03月22日
    浏览(43)
  • UDP套接字的通信(实现英汉互译/程序替换/多线程聊天室/Windows与Linux通信)

    我们在客户端发英文,服务端做翻译工作,让翻译好的中文再次发给我们的客户端,然后打印出来。 翻译的操作 创建一个txt文件里面包含英汉互译的数据 dict.txt 对txt中的数据进行操作 分割函数 将英汉通过冒号分开。 将文件数据插入map里面 重新加载文件 通过捕捉2号(ctrl

    2024年02月11日
    浏览(38)
  • VMware WiIN7 虚拟机安装wm-tools 时报错 安装程序无法自动安装Virtual Machine Communication Interface Sockets(VSock)驱动程序

    关于 VMware Tools安装时出现的问题的解决办法: 安装时出现问题对话框: 安装程序无法自动安装Virtual Machine Communication Interface Sockets(VSock)驱动程序。必须手动安装此驱动程序 可以通过安装windows更新解决,路径: https://support.microsoft.com/en-us/topic/servicing-stack-update-for-windows-

    2024年02月05日
    浏览(48)
  • 【Linux之进程间通信】04.Linux进程间的信号通信

      【Linux之进程间通信】 项目代码获取: https://gitee.com/chenshao777/linux-processes.git (麻烦点个免费的Star哦,您的Star就是我的写作动力!) 04.Linux进程间的信号通信 【目录】   一、进程间信号发送方式   二、进程间信号接收方式   三、进程间信号处理方式 一、进程间信号发

    2024年02月06日
    浏览(44)
  • 详解Windows系统下面如何查看CUDA、cuDNN、Python和各个软件包的版本

    这个题目网络上有很多的讲解,但是 查看CUDA、cuDNN版本 和 查看Python与自身各个软件包 是分开的,且cuDNN版本的查看方式似乎已经过时【截止2023-10-23】。由于自身需要且出于回馈 互联网大学 的目的,将相关内容重新整理在此篇博客中。 方法1:在Windows终端中通过以下3条下命

    2024年02月04日
    浏览(61)
  • 【Linux】进程通信之匿名管道通信

    我们往往需要多个进程协同,共同完成一些事情。 数据传输:一个进程需要将它的数据发送给另一个进程 资源共享:多个进程之间共享同样的资源。 通知事件:一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止 时要通知父进程)。

    2024年04月14日
    浏览(46)
  • 【Linux】进程通信之管道通信详解

    🍎 作者: 阿润菜菜 📖 专栏: Linux系统编程 其实管道通信是Unix中最古老的进程间通信的形式了: 管道通信是一种进程间通信的方式,它可以让一个进程的输出作为另一个进程的输入,实现数据的传输、资源的共享、事件的通知和进程的控制。 管道通信分为两种类型:匿名

    2023年04月19日
    浏览(41)
  • Linux--进程间的通信--进程池

    进程间的通信–匿名管道 进程池是一种将多个进程组织起来以执行特定任务的机制 。 它由多个预先创建好的资源进程和一个管理进程组成。这些资源进程被管理进程负责分配和调度,用于处理任务 。 当有新的任务提交时,管理进程会从进程池中取出一个资源进程,将任务

    2024年04月25日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包