深入理解和实现Windows进程间通信(消息队列)
常见的进程间通信方法
常见的进程间通信方法有:
- 管道(Pipe)
- 消息队列
- 共享内存
- 信号量
- 套接字
下面,我们将详细介绍消息队列的原理以及具体实现。
什么是消息队列?
Windows操作系统使用消息机制来促进应用程序与操作系统之间的通信。每当发生事件(如键盘按键、鼠标移动或系统事件)时,操作系统都会生成相应的消息。这些消息被发送到一个特定的消息队列中,随后由应用程序的消息循环处理。
消息队列
每个创建了窗口的线程都拥有一个消息队列,用于存储等待处理的消息。这些消息包括用户动作(如鼠标点击、键盘操作)和系统通知(如窗口重绘请求、系统关闭通知)。
消息循环
线程通过一个循环机制,称为消息循环或消息泵,从其消息队列中检索消息。消息循环的基本操作包括:
- 检索消息:使用
GetMessage
或PeekMessage
。 - 翻译消息:
TranslateMessage
转换键盘输入。 - 分发消息:
DispatchMessage
将消息派发给目标窗口的窗口过程。
消息分类
消息主要包含:
- 系统消息:涉及窗口生命周期管理,如
WM_CLOSE
和WM_QUIT
等。 - 硬件消息:反映用户与硬件的交互,如
WM_KEYDOWN
和WM_MOUSEMOVE
等。
除了上面提到的消息外,用户还可以自定义消息,自定义消息一般从WM_USER
(0x0400)开始,到0x7FFF这样一个范围内,比如:#define WM_CUSTOM_MSG WM_USER+100
接口介绍
GetMessage
、PeekMessage
、SendMessage
、PostMessage
这四个接口是Windows消息处理的核心,它们各自承担着不同的角色和功能。
GetMessage
原型
BOOL GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax
);
参数解释
- lpMsg:指向
MSG
结构的指针,该结构将接收消息的详细信息。 - hWnd:指定窗口的句柄,如果为
NULL
,则接收属于调用线程的任何窗口的消息。 - wMsgFilterMin和wMsgFilterMax:指定要检索的消息范围的最小值和最大值。如果两者都为0,函数将返回所有可用的消息。
功能和特点
GetMessage
用于从调用线程的消息队列中检索消息。该函数在有消息到达时返回,如果遇到退出消息WM_QUIT
,则返回FALSE
。- 该函数是阻塞的,如果没有消息,它会等待消息的到来。
PeekMessage
原型
BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg
);
参数解释
- lpMsg:指向
MSG
结构的指针,该结构将接收消息的详细信息。 - hWnd:指定窗口的句柄,如果为
NULL
,则获取属于调用线程的任何窗口的消息。 - wMsgFilterMin和wMsgFilterMax:指定要检索的消息范围的最小值和最大值。
- wRemoveMsg:指定消息如何处理。常用值有:
PM_REMOVE
、PM_NOREMOVE
。
功能和特点
PeekMessage
用于非阻塞地检查调用线程的消息队列,允许你查看消息队列中的消息而不必移除它。- 可以配置为从队列中移除消息或仅检查消息而不移除。
- 常用于动画或游戏编程中,确保应用程序保持响应用户操作,同时继续进行其它处理。
SendMessage
原型
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam
);
参数解释
- hWnd:接收消息的窗口的句柄。
- Msg:消息的标识符。
- wParam 和 lParam:消息特定的附加信息。
功能和特点
SendMessage
同步发送消息,调用方在接收窗口处理该消息之前会阻塞。- 可用于发送任何类型的消息,并且能够获取消息处理的结果。
PostMessage
原型
BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam
);
参数解释
- hWnd:接收消息的窗口的句柄。
- Msg:消息的标识符。
- wParam 和 lParam:消息特定的附加信息。
功能和特点
PostMessage
异步发送消息,将消息放入消息队列后立即返回,不等待消息被处理。- 适合用于那些不需要立即反馈的消息发送,如状态更新或通知消息。
实现
问题
实现两个进程,进程1发送消息给进程2,相关代码如下:
// 进程1
int main()
{HWND hWnd = FindWindow(NULL, L"WindowsProject1"); // 找到进程2的句柄const wchar_t* message = L"Hello!";if (hWnd != NULL) {SendMessage(hWnd, WM_USER+100, 0, (LPARAM)message);}std::cin.get();
}
// 进程2
#define WM_CUSTOMMSG (WM_USER+100)
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case WM_CUSTOMMSG: {wchar_t* receivedMessage = reinterpret_cast<wchar_t*>(lParam);SetWindowText(hLabel, receivedMessage);}break;...}return 0;
}
进程1通过自定义消息(WM_USER+100
)发送了一个字符串给进程2,进程2的确收到了消息,但是数据获取失败。
因为进程1准备发送的数据存储在进程1的虚拟内存中,进程2是无法通过地址来获取这个数据的,所以进程2虽然收到消息了,但是无法得到对应的数据。
所以在进程间通过消息队列通信时需要保证传递的数据的安全性。
WM_COPYDATA
WM_COPYDATA
是一个Windows消息,用于在Windows应用程序之间传递数据。这个消息特别适用于跨进程通信,允许一个应用程序向另一个应用程序的窗口发送数据,无论这些数据是简单的数值、字符串还是更复杂的结构通。
原理
当一个应用程序需要向另一个应用程序发送数据时,它可以将数据封装在COPYDATASTRUCT
结构中,并通过SendMessage
函数发送WM_COPYDATA
消息。当接收窗口的窗口过程收到这条消息时,它可以从COPYDATASTRUCT
结构中提取数据。
COPYDATASTRUCT结构
这个结构用于封装要传递的数据,其定义如下:
typedef struct tagCOPYDATASTRUCT {ULONG_PTR dwData; // 任意值,由发送方设置,接收方可以用它来识别数据DWORD cbData; // lpData指向的数据的大小,以字节为单位PVOID lpData; // 指向要传递的数据的指针
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
- dwData:这是一个用户定义的数据值,发送方可以使用它来传递额外的信息或数据类型标识,接收方则可以用它来决定如何解释接收到的数据。
- cbData:这表示 lpData 指向的数据的大小(以字节为单位)。
- lpData:这是一个指针,指向实际要传输的数据。
实现代码
进程1代码
int main()
{HWND hWnd = FindWindow(NULL, L"WindowsProject1");const wchar_t* message = L"Hello!";if (hWnd != NULL) {COPYDATASTRUCT cds;cds.dwData = 1; // 用于识别数据的自定义标识cds.cbData = (wcslen(message) + 1) * sizeof(wchar_t); // 包括终止符的大小cds.lpData = (void*)message;SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds);}std::cin.get();
}
进程2代码
HWND hLabel;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{hInst = hInstance; // 将实例句柄存储在全局变量中HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);if (!hWnd){return FALSE;}hLabel = CreateWindowW(L"STATIC", L"Waiting for message...",WS_CHILD | WS_VISIBLE | SS_LEFT,10, 10, 300, 20,hWnd, (HMENU)1, hInstance, nullptr);ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE;
}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{switch (message){case WM_COPYDATA: {PCOPYDATASTRUCT pCds = (PCOPYDATASTRUCT)lParam;if (pCds->dwData == 1) {const wchar_t* receivedStr = (const wchar_t*)pCds->lpData;SetWindowText(hLabel, receivedStr);}}break;case WM_COMMAND:{int wmId = LOWORD(wParam);// 分析菜单选择:switch (wmId){case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}}break;case WM_PAINT:{PAINTSTRUCT ps;HDC hdc = BeginPaint(hWnd, &ps);// TODO: 在此处添加使用 hdc 的任何绘图代码...EndPaint(hWnd, &ps);}break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}
效果
相关文章:
深入理解和实现Windows进程间通信(消息队列)
常见的进程间通信方法 常见的进程间通信方法有: 管道(Pipe)消息队列共享内存信号量套接字 下面,我们将详细介绍消息队列的原理以及具体实现。 什么是消息队列? Windows操作系统使用消息机制来促进应用程序与操作系…...
Web网页前端教程免费:引领您踏入编程的奇幻世界
Web网页前端教程免费:引领您踏入编程的奇幻世界 在当今数字化时代,Web前端技术已成为互联网发展的重要驱动力。想要踏入这一领域,掌握相关技能,却苦于找不到合适的教程?别担心,本文将为您带来一份免费的We…...
北斗短报文终端在应急消防通信场景中的应用
在应对自然灾害和紧急情况时,北斗三号短报文终端以其全球覆盖、实时通信和精准定位的能力,成为应急消防通信的得力助手。它不仅能够在地面通信中断的极端条件下保障信息传递的畅通,还能提供精准的位置信息,为救援行动提供有力支持…...
Java跳动爱心代码
1.计算爱心曲线上的点的公式 计算爱心曲线上的点的公式通常基于参数方程。以下是两种常见的参数方程表示方法,用于绘制爱心曲线: 1.1基于 (x, y) 坐标的参数方程 x a * (2 * cos(θ) - sin(θ))^3 y a * (2 * sin(θ) - cos(θ))^3 其中ÿ…...
Swift Combine — Operators(常用Filtering类操作符介绍)
目录 filter(_: )tryFilter(_: )compactMap(_: )tryCompactMap(_: )removeDuplicates()first(where:)last(where:) Combine中对 Publisher的值进行操作的方法称为 Operator(操作符)。 Combine中的 Operator通常会生成一个 Publisher,该 …...
Windows11+CUDA12.0+RTX4090如何配置安装Tensorflow2-GPU环境?
1 引言 电脑配置 Windows 11 cuda 12.0 RTX4090 由于tensorflow2官网已经不支持cuda11以上的版本了,配置cuda和tensorflow可以通过以下步骤配置实现。 2 步骤 (1)创建conda环境并安装cuda和cudnn,以及安装tensorflow2.10 con…...
韩顺平0基础学Java——第27天
p548-568 明天开始坦克大战 Entry 昨天没搞明白的Map、Entry、EntrySet://GPT教的 Map 和 Entry 的关系 1.Map 接口:它定义了一些方法来操作键值对集合。常用的实现类有 HashMap、TreeMap 等。 2. Entry接口:Entry 是 Map 接口的一个嵌…...
YesPMP探索Python在生活中的应用,助力提升开发效率
Python是一种简单易学、高效强大的编程语言,正变成越来越多人选择的热门技能。学习Python不仅可以提供更多就业机会,还能让自己在职场更加有竞争力,那可以去哪里拓展自己的技能呢? YesPMP平台 为熟练掌握Python语言的程序员提供了…...
TikTok账号运营:静态住宅IP为什么可以防封?
静态住宅IP代理服务是一种提供稳定、静态IP地址并可隐藏用户真实IP地址的网络代理服务。此类代理服务通常使用高速光纤网络来提供稳定、高速的互联网体验。与动态IP代理相比,静态住宅IP代理的IP地址更稳定,被封的可能性更小,因此更受用户欢迎…...
linux系统宝塔服务器temp文件夹里总是被上传病毒php脚本
目录 简介 上传过程 修复上传漏洞 tmp文件夹总是被上传病毒文件如下图: 简介 服务器时不时的会发送短信说你服务器有病毒, 找到了这个tmp文件, 删除了之后又有了。 确实是有很多人就这么无聊, 每天都攻击你的服务器。 找了很久的原因, 网上也提供了一大堆方法,…...
HTML+CSS+PHP实现网页留言板功能(需要创建数据库)
话说前头,我这方面很菜滴。这是我网页作业的一部分。 1.body部分效果展示(不包括footer) 2、代码 2.1 leaving.php(看到的网页) <!DOCTYPE html> <html lang"en"> <head> <met…...
【谷歌】实用的搜索技巧
1、使用正确的谷歌网址 我们知道https://www.google.com是谷歌的网址。但根据国家,用户可能会被重定向到 google.fr(法国)或google.co.in(印度)。 最主要的URL——google.com是为美国用户准备的(或是针对全世界所有用户的唯一URL))。当你在谷歌上搜索时,了解这一点是相…...
打造完美启动页:关键策略与设计技巧
启动页(Splash Screen)设计是指在应用程序启动时,首先展示给用户的界面设计。这个界面通常在应用加载或初始化期间显示,其主要目的是为用户提供一个视觉缓冲,展示品牌标识,并减少用户在等待过程中的焦虑感。…...
电子书(chm)-加载JS--CS上线
免责声明: 本文仅做技术交流与学习... 目录 cs--web投递 html(js)代码 html生成chm工具--EasyCHM 1-选择powershell 模式 生成 2-选择bitsadmin模式生成 chm反编译成html cs--web投递 cs配置监听器--->攻击---->web投递---> 端口选择没占用的, URL路径到时候会在…...
理解HTTP请求格式
HTTP概念 HTTP全称HyperTextTransfer Protocol(超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议;HTTP是一个客户端(用户)和服务端(网站)之间请求和响应的标准。 HTTP 协议是以 ASCII 码传输&…...
差分数组汇总
本文涉及知识点 算法与数据结构汇总 差分数组 令 a[i] ∑ j : 0 i v D i f f [ i ] \sum_{j:0}^{i}vDiff[i] ∑j:0ivDiff[i] 如果 vDiff[i1],则a[i1…]全部 如果vDiff[i2]–,则a[i2…]全部–。 令11 < i2 ,则: { a [ i ] 不变&…...
SpringBoot | 实现邮件发送
运行环境: IntelliJ IDEA 2022.2.5 (Ultimate Edition) (注意:idea必须在2021版本以上)JDK17 项目目录: 该项目分为pojo,service,controller,utils四个部分, 在pojo层里面写实体内容(发邮件需要的发件人邮…...
spring boot接入nacos 配置中心
再接入nacos配置中心时,需要确认几点: 1. spring boot 版本 (spring boot 2.x ) 2. nacos 配置中心 服务端 版本 (1.1.4) 3. nacos client 客户端版本 (1.1.4) 方式一 1. 启动 nacos 服务端,这里不做解释 在配置中心中加入几个配置 2. 在…...
产品应用 | 小盒子跑大模型!英码科技基于算能BM1684X平台实现大模型私有化部署
当前,在人工智能领域,大模型在丰富人工智能应用场景中扮演着重要的角色,经过不断的探索,大模型进入到落地的阶段。而大模型在落地过程中面临两大关键难题:对庞大计算资源的需求和对数据隐私与安全的考量。为应对这些挑…...
uniapp中u-input点击事件失效
当给u-input设置了disabled/readonly属性后,pc浏览器中点击事件失效,但是app/移动端h5中却仍有效 解决办法 给外边包上一个盒子设置点击事件,给input加上css属性:pointer-events:none pointer-events CSS 属性指定在什…...
[机器学习] 监督学习和无监督学习
监督学习和无监督学习是机器学习的两种主要方法,它们之间有几个关键区别: 1. 定义 监督学习(Supervised Learning): 使用带标签的数据进行训练。数据集包括输入特征和对应的输出标签。目标是学习从输入特征到输出标签…...
使用Python进行自然语言处理:从基础到实战
使用Python进行自然语言处理:从基础到实战 自然语言处理(Natural Language Processing, NLP)是人工智能的重要领域,旨在处理和分析自然语言数据。Python凭借其丰富的库和社区支持,成为NLP的首选编程语言。本文将介绍自然语言处理的基础概念、常用的Python库以及一个实战项…...
Hadoop面试题总结
一 、介绍一下hadoop 综述:hadoop是一个适合海量数据的分布式存储和分布式计算的平台 分述:hadoop包含三大组件,分别是HDFS、MapReduce和YARN --HDFS(分布式文件系统) HDFS集群由NameNode,DataNode,SecondaryNameNode构成NameNode:主要负责接受用户请求…...
关于IntelliJ IDEA 2024.1版本更新的问题
希望文章能给到你启发和灵感~ 感谢支持和关注~ 阅读指南 序幕一、基础环境说明1.1 硬件环境1.2 软件环境 二、起因三、解决四、总结 序幕 近期,IntelliJ IDEA 推出了全新2024版本,相信很多编程的爱好者或者刚接触编程的小伙伴都会…...
双层循环和循环语句
echo 打印 echo -n 表示不换行输出 echo -e 表示输出转义字符 echo \b 相当于退格键(backspace) echo \n 换行,相当于回车 echo \f 换行,换行后的新行的开头连着上一行的行尾 echo \t 相当于tab健 (…...
【Codesys】-计算开机通电运行时间,累计正常使用时间,故障停机时间
应客户要求,在程序添加了这个用来计算开机运行时间,原理就是取当前时间减去一开始记录的时间,没什么特别要求,记录一下使用的变量类型和数据写法,防止忘记了。 下文只写了一个开机通电运行时间的写法,累计…...
LINUX系统编程:线程的概念
目录 1.线程的概念 2.线程的理解 3.怎么做到划分代码的 本文主要介绍,在LIUNX下的线程。 1.线程的概念 在很多的书上的你可能见过这样的。 线程是进程内部的一个执行分支,线程是cpu调度的基本单位。 加载到内存的程序叫做进程。修正:进…...
如何更换OpenHarmony SDK API 10
OpenHarmony社区已经发布OpenHarmony SDK API 10 beta版本,有些 Sample案例 也有需要API10。那么如何替换使用新的OpenHarmony SDK API 10呢?本文做个记录。 1、如何获取OpenHarmony SDK 1.1 每日构建流水线 可以从OpenHarmony每日构建站点获取最新的…...
Java | Leetcode Java题解之第155题最小栈
题目: 题解: class MinStack {Deque<Integer> xStack;Deque<Integer> minStack;public MinStack() {xStack new LinkedList<Integer>();minStack new LinkedList<Integer>();minStack.push(Integer.MAX_VALUE);}public void …...
大润发超市购物卡怎么用?
收到大润发超市的礼品卡以后,我才发现,最近的大润发也得十来公里 为了100块的大润发打车也太不划算了 叫外送也不在配送范围内 最后没办法,在收卡云上出掉了,还好最近价格不错,也不亏,收卡云的到账速度也…...
物流网站系统php源码/人脉推广app
保护嵌入式设备的安全正在成为一个热门话题,尤其是当这些设备开始连接到互联网时。黑客对连接的设备进行逆向工程是一个真正的威胁,这种攻击很容易做到。嵌入式开发人员可以做些什么来提高他们设备的安全性? 以下是开发人员需要注意的七个关键要点。 要…...
做网站需要买空间么 服务器/免费个人推广引流平台
2019独角兽企业重金招聘Python工程师标准>>> /*** 使用方法:* 开启:MaskUtil.mask();* 关闭:MaskUtil.unmask();* * MaskUtil.mask(其它提示文字..);*/ var MaskUtil (function(){ var $mask,$maskMsg; var defMsg 正在处理,,请稍待。。。;…...
六灶网站建设/嘉兴网站建设方案优化
当我们的服务器某台故障的时候,我们的SCOM肯定是最早发现它的时候,但SCOM发现了以后怎么告诉IT管理员来维护呢?默认情况下肯定是需要IT管理员主动登陆到SCOM服务器上来查看其他所有服务器的运行状况,这对及时处理问题带来了延迟&a…...
建设网站免费/营销必备十大软件
Linux 4.9-rc1版本已于近日发布下载,这标志着4.9内核合并窗口宣告结束。正因为如此,本文盘点了Linux 4.9的种种变化,它们让我们为这个开源内核的下一个版本而感到激动。一些亮点包括:AMDGPU GCN 1.0试验性支持、内存保护密钥支持、…...
关于京东商城网站建设的实践报告/网络游戏推广平台
Hadoop是什么? 适合大数据的分布式存储于计算平台 不适用小规模数据 作者:Doug Cutting 受Google三篇论文的启发 Hadoop核心项目 HDFS(Hadoop Distrubuted File System) 分布式文件系统 MapReduce 并行计算框架 版本 Apache 官方版…...
wordpress大开速度慢/百度指数关键词未收录怎么办
“Window” –> “Preferences” 然后选择 Maven选项, 然后选择 “Download repository index updates on startup” 如果没有 “Search Results” 那么”Window” —> “Show View” —> “Maven Repositories” —> “Global Repositories” 选择…...