[MFC] MFC消息机制的补充

news2024/10/7 18:28:50

之前写了[MFC] 消息映射机制的使用和原理浅析,还有些需要补充的,都记在这里。

MFC 消息的分类

MFC消息分为系统消息和自定义消息。
在这里插入图片描述
图片来源:C语言/C++教程 大型源码案例分析:MFC消息系统的代码解析 易道云编程

系统消息分为窗口消息、命令消息、通知消息。消息ID是0 ~ 1023。
每个窗口的自定义消息的消息ID需要从1024开始。声明方法为:

#define MY_MSG_1 (WM_USER + 1)

SendMessage

[MFC] 消息映射机制的使用和原理浅析中,用SendMessage发了一个消息。

void CMFCApplication1Dlg::OnBnClickedButton1()
{
	::SendMessage(this->GetSafeHwnd(),MY_MSG_1,NULL,NULL);	
}

SendMessage发出的消息是不经过消息循环的。
所以debug时可以看到,没有经过任何loop函数,直接就是AfxWndProc了,最终通过MessageMap找到对应的响应函数。
此时的函数堆栈调用:
在这里插入图片描述

未排队的消息
未排队的消息会立即发送到目标窗口过程,绕过系统消息队列和线程消息队列。 系统通常发送未排队的消息,以通知窗口影响它的事件。 例如,当用户激活新的应用程序窗口时,系统会向窗口发送一系列消息,包括 WM_ACTIVATE、 WM_SETFOCUS和 WM_SETCURSOR。 这些消息通知窗口已激活,键盘输入已定向到窗口,鼠标光标已在窗口边框内移动。 当应用程序调用某些系统函数时,也可能导致未排队的消息。 例如,在应用程序使用 SetWindowPos 函数移动窗口后,系统会发送WM_WINDOWPOSCHANGED消息。
发送非排队消息的一些函数包括 BroadcastSystemMessage、 BroadcastSystemMessageEx、 SendMessage、 SendMessageTimeout 和 SendNotifyMessage。
来源:Microsoft Learn 关于消息和消息队列

PostMessage 和 消息循环

把上面的SendMessage改成PostMessage试一下。

void CMFCApplication1Dlg::OnBnClickedButton1()
{
	::PostMessage(this->GetSafeHwnd(),MY_MSG_1,NULL,NULL);	
}

此时的函数堆栈调用:
在这里插入图片描述
可以看到调用堆栈不同。
在进入AfxWndProc之前,进入了RunModalLoop。
RunModalLoop就是CWnd的消息循环处理函数。

所以用SendMessage发出的消息,没有经过消息队列。
使用PostMessage发出的消息,会进入系统的消息队列,需要窗口的消息循环来处理。

线程可以使用 PostMessage 或 PostThreadMessage 函数将消息发布到其自己的消息队列或另一个线程的队列。
来源:Microsoft Learn 关于消息和消息队列

消息循环中,主要做了以下事情:
第一个循环:

// phase1: check to see if we can do idle work
while (bIdle &&
			!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE))
......

PeekMessage 消息,获取消息,而不在队列中删除消息。这里对PeekMessage的返回值进行了非判断,当取不到消息的时候,进行IDLE空闲判断和处理。

第二个循环:

// phase2: pump messages while available
do
{
	......
}while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));

这个循环也是PeekMessage获取消息,然后在循环体中,进行pump meessage(消息泵)

// pump message, but quit on WM_QUIT
if (!AfxPumpMessage())

AfxPumpMessage中,会GetMessage()、AfxPreTranslateMessage()、TranslateMessage()、DispatchMessage()。

系统为每个 GUI 线程维护一个系统消息队列和一个特定于线程的消息队列。
~
每当用户移动鼠标、单击鼠标按钮或键盘上的类型时,鼠标或键盘的设备驱动程序会将输入转换为消息,并将其置于系统消息队列中。 系统一次从系统消息队列中删除一个消息,检查它们以确定目标窗口,然后将其发布到创建目标窗口的线程的消息队列。 线程的消息队列接收线程创建的窗口的所有鼠标和键盘消息。 线程从其队列中删除消息,并指示系统将其发送到相应的窗口过程进行处理。
来源:Microsoft Learn 关于消息和消息队列

PreTranslateMessage和WindowProc

这里提一下PreTranslateMessage函数。
PreTranslateMessage是一个虚函数。它在TranslateMessage和DispatchMessage之前触发。当它返回true时,消息不会再发送给TranslateMessage和DispatchMessage。当它返回false时,消息会继续发送给TranslateMessage和DispatchMessage。

对于窗口类,可以重写自己的PreTranslateMessage()。这样可以捕获消息来进行一些自定义处理。
它只能捕获经过消息队列的消息,不经过消息队列的消息无法捕获。

WindowProc函数也是可以捕获消息,对消息进行自定义处理的。
PreTranslateMessage和WindowProc的区别在于:

  1. 只有经过消息队列的消息PreTranslateMessage才捕获的到。比如SendMessage发出的本窗口消息,不经过消息队列,PreTranslateMessage没反应,但是WindowProc捕获得到。
  2. 根据上面写的消息循环部分,可以知道,每个线程都有一个消息循环,它从线程的消息对列中获取消息,然后对消息进行TranslateMessage()、DispatchMessage(),DispatchMessage会把消息发送给对应的窗口。PreTranslateMessage就是重写的位于TranslateMessage之前的函数。WindowProc是窗口用于接收消息的函数。这个两个函数的调用位置是不同的。

1:
MFC中PreTranslateMessage是GetMessage(…)函数的下一级操作,即GetMessage(…)从消息队列中获取消息后,交由PreTranslateMessage()处理,若其返回FALSE则再交给TranslateMessage和DispatchMessage处理(进入WindowProc);
如果用SendMessage, 则消息直接交到WindowProc处理,所以GetMessage不会取得SendMessage的消息,当然PreTranslateMessage也就不会被调用。
如果用PostMessage,则消息进入消息队列,由GetMessage取得,PreTranslateMessage就有机会进行处理。
2:
SendMessage要区分环境,如果是对本线程的窗口SendMessage,则不经过任何消息循环,也不放入消息队列,直接调用WindowProc,所以GetMessage和PreTranslateMessage都捕获不到;如果SendMessage是向其它线程或其它进程的窗口发消息,则消息进入消息队列,GetMessage和PreTranslateMessage能捕获到这个消息。
原文:VC++ PreTranslateMessage和WindowProc的使用总结

原文链接:https://blog.csdn.net/libaineu2004/article/details/90600433

参考

C语言/C++教程 大型源码案例分析:MFC消息系统的代码解析 易道云编程

SendMessage() 发出的消息 PreTranslateMessage() 不一定能接收到!

Microsoft Learn 关于消息和消息队列

MFC学习(一):MFC的消息循环 --讲解到位

VC++ PreTranslateMessage和WindowProc的使用总结

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

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

相关文章

【SpringBoot】SpringBoot的web开发

📝个人主页:五敷有你 🔥系列专栏:SpringBoot ⛺️稳重求进,晒太阳 Wbe开发 使用Springboot 1)、创建SpringBoot应用,选中我们需要的模块; 2)、SpringBoot已经默…

用友GRP-U8 listSelectDialogServlet SQL注入漏洞复现

0x01 产品简介 用友GRP-U8R10行政事业内控管理软件是用友公司专注于国家电子政务事业,基于云计算技术所推出的新一代产品,是我国行政事业财务领域最专业的政府财务管理软件。 0x02 漏洞概述 用友GRP-U8R10行政事业内控管理软件 listSelectDialogServlet 接口处存在SQL注入…

chisel RegInit/UInt/U

val reg RegInit(0.U(8.W)) //ok val reg RegInit(0.UInt(8.W)) //errU 使用在数字 . 后边50.U UInt 使用在IO(new Bundle val a Input(UInt(8.W)) 或者 def counter(max:UInt, a1:UInt) package emptyimport chisel3._ import chisel3.util._class MyCounter extends …

操作系统-【预备学习-1】(Linux 文件目录)

文章目录 相关知识目录结构进入目录补充查看目录创建文件删除文件创建文件夹删除文件夹文件和文件夹拷贝文件和文件夹移动/重命名 任务要求 相关知识 目录结构 Linux 文件系统是树形层次结构,具体如下图所示,最重要的是根目录(/&#xff09…

06 - python操作xml

认识XML 与HTML很像,是一种将数据存储在标记之间的标记语言,用户可以自定义自己的标记。 XML文件可以表示称为:XML树。这个XML树从根元素开始,根元素进一步分支到子元素。XML文件的每个元素都是XML树的一个节点,没有…

服务器和云服务器哪个更安全?

随着云计算技术的不断发展,越来越多的企业开始选择使用云服务器来存储和处理数据。然而,对于一些企业来说,他们可能更倾向于使用传统的服务器。在这种情况下,安全性成为了一个重要的考虑因素。那么,服务器和云服务器哪…

arm 汇编积累

C语言函数与汇编对应关系 一、MOV 系列指令 1、指令格式 MOV{条件}{S} 目的寄存器,源操作数 2、含义解析: (1):mov 指令传送数据 案例: MOV R0,R1 ; R0 R1; MOV PC,R14 ;PC R14; MOV R0,R…

[Angular 基础] - 数据绑定(databinding)

[Angular 基础] - 数据绑定(databinding) 上篇笔记,关于 Angular 的渲染过程及组件的创建&简单学习:[Angular 基础] - Angular 渲染过程 & 组件的创建 Angular 之中的 databinding 是一个相对而言更加复杂,以及我个人觉得相对而言比…

Java on Azure Tooling 2024年1月更新|Azure Key Vault 支持、示例项目创建支持及更多

作者:Jialuo Gan - Program Manager, Developer Division At Microsoft 排版:Alan Wang 大家好,欢迎来到 2024 年 Java on Azure 工具的首次更新。在本次更新中,我们将介绍对于 Azure Key Vault 支持、基于 Azure 示例项目的创建支…

C++ 调用lua 脚本

需求: 使用Qt/C 调用 lua 脚本 扩展原有功能。 步骤: 1,工程中引入 头文件,库文件。lua二进制下载地址(Lua Binaries) 2, 调用脚本内函数。 这里调用lua 脚本中的process函数,并…

如何让虚拟机拥有愉快网络环境,vmware,ubuntu,centos

博客原文 文章目录 前言拥有愉快网络环境步骤:测试网关连接 Ubuntu修改 http 与 sock 代理地址修改 /etc/resolv.conf配置 apt 使用代理测试连接 Centos设置代理地址修改 NetworkManager最后重启网卡:测试代理 前言 相信计算机专业的同学在学习 linux 时, 一定会被无…

Element UI+Spring Boot进行CRUD的实例

ElementUI安装与使用指南 前端代码:点击查看learnelementuispringboot项目源码 后端代码:点击查看 LearnElementUiAndSpringBoot 一、前端配置 安装axios Gitee的axios介绍与使用 GitHub的axios介绍与使用 方式一:使用npm安装 $ npm in…

2024年最新幻兽帕鲁服务器搭建教程

玩转幻兽帕鲁服务器,阿里云推出新手0基础一键部署幻兽帕鲁服务器教程,傻瓜式一键部署,3分钟即可成功创建一台Palworld专属服务器,成本仅需26元,阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…

回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制) 目录 回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制&…

谷歌产品大更新:Bard可生成图像;文生音乐平台等5大免费功能

2月2日,谷歌在官网对生成式AI产品进行了大更新,包括类ChatGPT聊天助手Bard可以通过文本提示生成图像; 全新的文生音乐平台MusicFX;新的文生图像平台ImageFX;新的文本扩写平台TextFX;在谷歌地图中增加生成式…

docker搭建Mysql集群准备(一)

docker搭建Mysql集群准备 Linux基本知识: 修改机器 IP,变成静态 IP vim /etc/sysconfig/network-scripts/ifcfg-ens33 文件 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic IPADDR192.168.190.67 NETMASK255.255.255.0 GAT…

第六讲:文件操作

第六讲:文件操作 文件夹创建文件夹移动文件夹复制文件夹删除文件夹文件操作文件读取文件写入文件文件夹 创建文件夹 定义创建文件夹函数:chmk_path()定义一个函数 chmk_path(),这个函数的功能是创建文件夹。 首先需要导入操作系统接口模块——os 模块,这个模块中包含某些函…

802.11n 802.11ac (WiFi 4/5 )的核心要点

802.11n 802.11ac (WiFi 4/5 )是什么? WiFi 4: Ieee 802.11n Enhancements for High Throughput (HT) WiFi 5: Ieee 802.11ac Enhancements for Very High Throughput (VHT&#x…

ywtool login guard命令

一.登录防护功能介绍 登录防护功能主要检查系统日志/var/log/secure,查看系统有没有被暴力登录。登录防护默认是检测3分钟内登录系统失败15次(次数可修改)后,视其为有攻击性,拉黑此IP(centos7通过系统文件阻止IP,centos8/9通过防火墙阻止IP)。此脚本只针对SSH访问,…

vscode 无法远程连接waiting the server log

使用版本 报错信息 相关日志 [17:32:59.765] > Waiting for server log... [17:32:59.801] > Waiting for server log... [17:32:59.831] > > * > * Visual Studio Code Server > * > * By using the software, you agree to > * the Visual Studio…