[MFC] MFC消息机制的补充

之前写了[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.rhkb.cn/news/254244.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

个人IP塑造与短视频带货,人人都是吸金的网红博主

一、教程描述 网红带货,就是网络红人通过推荐和分享,间接销售产品的一种方式。网红带货并不是直接带货,而是需要打造自己,用时下热门的话讲叫塑造IP,一般通过旅行、工作、日常服装搭配等这些行为,输出自己…

龙芯开启ssh服务——使用Putty连接

本文采用龙芯3A6000处理器,Loongnix操作系统。 为了能使用其他电脑远程操控龙芯电脑,需要打开loongnix的ssh服务,并在其他电脑里使用putty连接loongnix。 1 修改ssh配置文件 命令行输入: sudo vim /etc/ssh/sshd_config按下i插…

Unity3d Shader篇(六)— BlinnPhong高光反射着色器

文章目录 前言一、BlinnPhong高光反射着色器是什么?1. BlinnPhong高光反射着色器的工作原理2. BlinnPhong高光反射着色器的优缺点优点缺点 3. 公式 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数 三…

【数据分享】1929-2023年全球站点的逐月平均风速(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、能见度等指标,说到气象数据,最详细的气象数据是具体到气象监测站点的数据! 有关气象指标的监测站点数据,之前我们分享过1929-2023年全球气象站…

【精选】java初识多态 子类继承父类

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏…

08-Java过滤器模式 ( Filter Pattern )

Java过滤器模式 实现范例 过滤器模式(Filter Pattern)或允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来 过滤器模式(Filter Pattern) 又称 标准模式(Criteria Pattern…

C++:二叉搜索树模拟实现(KV模型)

C:二叉搜索树模拟实现(KV模型) 前言模拟实现KV模型1. 节点封装2、前置工作(默认构造、拷贝构造、赋值重载、析构函数等)2. 数据插入(递归和非递归版本)3、数据删除(递归和非递归版本…

校园墙表白墙系统uniapp微信小程序

配置文件 (自动编号、配置参数名称、配置参数值); 前端开发:vue 语言:javapythonnodejsphp均支持 运行软件:idea/eclipse/vscode/pycharm/wamp均支持 框架支持:Ssm/django/flask/thinkphp/springboot/springcloud均支持 数据库 mysql 数据库工具&#x…

【C++】C++的简要介绍

简单不先于复杂,而是在复杂之后。 文章目录 1. 什么是C2. C的发展史3. C的重要性3.1 语言的使用广泛度3.2 在工作领域3.3 在校招领域3.3.1 岗位需求3.3.2 笔试题 3.3.3 面试题 4. 如何学习C4.1 别人怎么学? 1. 什么是C C语言是结构化和模块化的语言&…

94.网游逆向分析与插件开发-游戏窗口化助手-地图数据获取的逆向分析与C++代码还原

内容参考于:易道云信息技术研究院VIP课 上一个内容:升级经验数据获取的逆向分析 码云地址(游戏窗口化助手 分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:c4351a5b346d8953a1a8e3ec…

文件上传-Webshell

Webshell简介 webshell就是以aspphpjsp或者cgi等网页文件形式存在的一种命令执行环境,也可以将其称做为一种网页木马后门。 攻击者可通过这种网页后门获得网站服务器操作权限,控制网站服务器以进行上传下载文件、查看数据库、执行命令等… 什么是木马 …

Oracle和Mysql数据库

数据库 Oracle 体系结构与基本概念体系结构基本概念表空间(users)和数据文件段、区、块Oracle数据库的基本元素 Oracle数据库启动和关闭Oracle数据库启动Oracle数据库关闭 Sqlplussqlplus 登录数据库管理系统使用sqlplus登录Oracle数据库远程登录解锁用户修改用户密码查看当前语…

【网工】华为设备命令学习(服务器发布)

本次实验主要是内网静态nat配置没,对外地址可以理解为一台内网的服务器,外网设备可以ping通内网的服务器设备,但是ping不通内网的IP。 除了AR1设备配置有区别,其他设备都是基础IP的配置。 [Huawei]int g0/0/0 [Huawei-GigabitEt…

前端框架学习 Vue(3)vue生命周期,钩子函数,工程化开发脚手架CLI,组件化开发,组件分类

Vue 生命周期 和生命周期的四个阶段 Vue生命周期:一个Vue实例从创建 到 销毁 的整个过程 生命周期四个阶段 :(1)创建 (2)挂载 (3)更新 (4)销毁 Vue生命周期函数(钩子函数) Vue生命周期过程中,会自动运行一些函数,被称为[生命周期钩子] ->让开发者可以在[特定阶段] 运行自…

【初识爬虫+requests模块】

爬虫又称网络蜘蛛、网络机器人。本质就是程序模拟人使用浏览器访问网站,并将需要的数据抓取下来。爬虫不仅能够使用在搜索引擎领域,在数据分析、商业领域都得到了大规模的应用。 URL 每一个URL指向一个资源,可以是一个html页面,一…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Span组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Span组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Span组件 鸿蒙(HarmonyOS)作为Text组件的子组件&#xff0…

【MySQL】:深入理解并掌握DML和DCL

🎥 屿小夏 : 个人主页 🔥个人专栏 : MySQL从入门到进阶 🌄 莫道桑榆晚,为霞尚满天! 文章目录 📑前言一. DML1.1 添加数据1.2 修改数据1.3 删除数据 二. DCL2.1 管理用户2.2 权限控制…

RabbitMQ-1.介绍与安装

介绍与安装 1.RabbitMQ1.0.技术选型1.1.安装1.2.收发消息1.2.1.交换机1.2.2.队列1.2.3.绑定关系1.2.4.发送消息 1.2.数据隔离1.2.1.用户管理1.2.3.virtual host 1.RabbitMQ 1.0.技术选型 消息Broker,目前常见的实现方案就是消息队列(MessageQueue&…

基于AST实现一键自动提取替换国际化文案

背景:在调研 formatjs/cli 使用(使用 formatjs/cli 进行国际化文案自动提取 )过程中,发现有以下需求formatjs/cli 无法满足: id 需要一定的语义化; defaultMessage和Id不能直接hash转换; 需要…

简化版SpringMVC

简化版SpringMVC web.xml xml version"1.0" encoding"UTF-8"?> <web-app version"2.5" xmlns"http://java.sun.com/xml/ns/javaee" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation&quo…