新书推荐:2.3 消息机制

news2024/11/23 14:53:49

Windows程序的消息机制是指在Windows操作系统下,应用程序与操作系统之间的一种通信方式。通过消息机制,应用程序可以接收来自操作系统的各种事件和请求,以便做出相应的响应和处理。

在Windows程序中,消息机制的实现是基于消息队列和消息循环的。消息队列是一个用于存储消息的缓冲区,当操作系统有消息需要传递给应用程序时,消息会被放入消息队列中。消息循环是应用程序的主循环,在消息循环的过程中,应用程序从消息队列中取出消息并进行处理。

Windows程序中的各种事件和请求都经过消息机制进行传递,比如鼠标点击、键盘输入、窗口尺寸改变等等。当发生这些事件时,操作系统会将相应的消息放入消息队列中,并通知应用程序有新的消息到达。应用程序在消息循环中不断地检查消息队列,处理队列中的消息,直到队列为空或者收到退出消息。

应用程序可以通过消息处理函数来响应不同类型的消息。当该类型的消息到达时,消息处理函数就会被调用,可以在该函数中编写相应的逻辑来处理消息。消息处理函数可以是在创建窗口时指定的窗口过程函数,或者是通过注册消息回调函数的方式来实现。绝大多数消息都是由Windwos系统默认的窗口过程来处理的。

本节必须掌握的知识点:

        消息队列

        消息循环

2.3.1 消息队列

       Windows程序中的消息队列是属于线程的。每个线程初始化时都可以创建一个线程所属的消息队列。但通常在Windows程序中,只有负责处理窗口消息的主线程创建消息队列,因此,我们将线程消息队列也称之为窗口消息队列。通常Windows程序将与用户交互的消息送入消息队列进行同步。例如鼠标消息、键盘消息、绘图消息等。

       此外,一些不需要同步的消息会直接分发给窗口过程进行处理,不进入消息队列。

       ■Windows系统消息队列

       Windows操作系统是多任务系统,通常同时有多个窗口程序在运行。所有进程的消息都会被送入Windows系统内的总消息队列。然后再将总消息队列中的消息按照所属的窗口分发给每个进程的窗口消息队列。这就需要判断消息应该属于哪个窗口。

在Windows程序中,消息是通过窗口句柄来进行分发和处理的。每个窗口都有一个唯一的窗口句柄(HWND),它用于标识和引用该窗口。通过窗口句柄,可以将收到的消息正确地分发给相应的窗口。

当Windows操作系统产生一个消息并将其放入消息队列时,消息中会包含目标窗口的句柄。然后,在应用程序的消息循环中,通过处理该消息的程序会根据消息中的窗口句柄,将消息分发给对应的窗口进行处理。

在处理消息的过程中,应用程序可以使用窗口句柄来识别消息应该属于哪个窗口。通常,在处理消息的代码中,可以使用如下方式来判断消息属于哪个窗口:

●检查消息中的窗口句柄与已创建的窗口句柄是否匹配。这可以通过保存窗口句柄的变量或数据结构来完成,然后将收到的消息中的窗口句柄与保存的窗口句柄进行比较。

●使用GetWindowLongPtr函数或GetWindowLong函数获取窗口的扩展信息(例如窗口的额外数据)。可以根据扩展信息中的标识或其他自定义数据来判断消息是属于哪个窗口。

●使用其它窗口属性或特征来判断。(例如窗口类名、窗口标题等)。

    问题似乎回到了原点,最初消息被Windows操作系统捕获时就应该确定其属于哪个窗口。我们分类来讨论。

       1.如果是鼠标消息,Windows系统会根据鼠标消息的坐标位置来确定它所处的位置属于哪个窗口。当然也有另外一种情况,就是一个窗口会主动捕获并拥有一个鼠标消息。

       2.如果是键盘消息,那么该键盘消息一定是属于当前处于焦点状态的窗口,即当前拥有键盘输入焦点的窗口。如果要想改变键盘消息所属的窗口,只能是切换焦点窗口。

       3.如果是子窗口控件、菜单、快捷键消息,其本身就属于指定的窗口,毋庸置疑。

       ■窗口消息队列

窗口消息队列是Windows操作系统中负责存储消息的一个缓冲区。每个线程都有自己的消息队列,用于接收和存储操作系统发送给应用程序的消息。在Windows程序中,消息队列起到了重要的作用,用于传递各种事件和请求,例如键盘输入、鼠标点击、窗口尺寸改变等。

消息队列是一个先进先出(FIFO)的数据结构,新的消息会被添加到队列的尾部,而从队列头部会取出最早进入队列的消息。当操作系统接收到一个消息时,会将该消息放入相应线程的消息队列中,然后通知该线程有新消息到达。

2.3.2 消息循环

应用程序可以通过消息循环来检查和处理消息队列中的消息。在消息循环中,应用程序会不断地从消息队列中取出消息进行处理,直到队列为空或者收到退出消息。

一般来说,消息循环具有以下形式:

while (GetMessage(&msg, NULL, 0, 0))

{

    TranslateMessage(&msg);

    DispatchMessage(&msg);

}

在这个消息循环中,GetMessage函数会从消息队列中取出一条消息,并将其存储在 msg 变量中。

键盘消息

如果是键盘按键消息,TranslateMessage函数会将虚拟键消息翻译为字符消息。它会检查消息的类型,如果是某些特殊键(如功能键、方向键等),则生成一个 WM_KEYDOWN 或 WM_KEYUP 消息;如果是一个字符键消息,则生成一个 WM_CHAR 消息。TranslateMessage 的作用是为了在键盘输入时生成合适的字符消息。接着将WM_CHAR 消息重新送入消息队列。

其他消息

其他消息则直接由DispatchMessage 函数将消息分发到相应的窗口过程函数进行处理。它会根据消息中的窗口句柄找到对应的窗口过程函数,并将消息传递给它。窗口过程函数负责处理具体的消息,它会根据消息类型和需要执行相应的逻辑,比如绘图、更新窗口状态、响应用户输入等。

总结一下,窗口消息队列是用于存储消息的缓冲区,当操作系统有消息需要传递给应用程序时,会将消息放入消息队列中。应用程序在消息循环中检查消息队列,从中取出消息并将其发送给相应的窗口过程函数进行处理。这样,应用程序能够接收并响应用户输入和操作系统事件。

在Windows程序中,如果是由我们主动发送消息呢?则需要调用下面两个函数。

●PostMessage函数:

PostMessage是一个Windows API函数,用于将一个消息放入与指定窗口关联的线程的消息队列中,等待线程处理。此消息并不会直接发送到窗口过程函数,而是立即返回,消息的处理可能会在稍后才进行。

以下是PostMessage函数的原型:

BOOL PostMessage(

  HWND   hWnd,      // 窗口句柄

  UINT   Msg,           // 消息

  WPARAM wParam,   // 额外的消息相关信息

  LPARAM lParam        // 额外的消息相关信息

);

参数含义:

hWnd:接收消息的窗口句柄。这可以是具体的窗口句柄,也可以是一些特殊值,如HWND_BROADCAST(指所有窗口)。如果此参数为NULL,则消息会发送给调用线程的消息队列。

Msg:需要发送的消息码,如WM_CLOSE。

wParam,lParam:与消息有关的额外信息。

PostMessage函数将消息投递到消息队列后就会立即返回,不管消息是否被目标窗口过程函数处理。也就是说PostMessage是异步的,主要用于在不要求立即处理消息的情况下通知其他窗口一个事件发生,比如通知其他窗口更新显示内容。

如果你希望立即发送并处理消息,应该使用SendMessage函数。不同于PostMessage,SendMessage会立即触发窗口的窗口过程函数处理消息,并等待处理完毕后返回。

●SendMessage函数:

SendMessage是一个Windows API函数,用于将一个消息发送到指定的窗口,并等待接收消息的窗口处理完该消息后返回。这个函数与PostMessage的最大区别就是:SendMessage是同步的,消息会立即被处理,而不是被投递到消息队列中等待处理。

以下是SendMessage函数的原型:

LRESULT SendMessage(

  HWND   hWnd,      // 窗口句柄

  UINT   Msg,           // 消息

  WPARAM wParam,     // 额外的消息相关信息

  LPARAM lParam        // 额外的消息相关信息

);

参数含义:

hWnd:接收消息的窗口句柄。这可以是具体的窗口句柄,也可以是一些特殊值。

Msg:需要发送的消息码,如WM_CLOSE。

wParam,lParam:与消息有关的额外信息。

SendMessage函数会立即调用目标窗口的窗口过程,传递给它消息码和额外信息,等待窗口过程处理完消息后再返回。这意味着在消息处理完成前,SendMessage函数会一直被阻塞。

请注意,对于可能会导致长时间等待的操作(如网络操作或大量计算),不应使用SendMessage进行处理,因为这可能造成应用程序的阻塞。此时,应使用PostMessage进行异步操作,或者设计一种将这种操作异步化的机制。

       ■窗口程序运行过程

       如图2-10所示,我们把Windows程序分为4个部分:Windows操作系统、主程序、窗口过程、其他应用程序。

       ●主程序我们已经非常熟悉了,分为五个固定的步骤,主程序的核心是一个消息循环,调用GetMessage函数不间断的从窗口消息队列获取消息。

       ●窗口过程负责处理消息,switch结构不处理的消息都交给DefWindProc默认窗口过程处理,处理后返回Windows系统。

       ●Windows操作存在一个总的消息队列和各个不同进程的窗口消息队列。Windows系统负责捕获消息或产生消息。如果是鼠标键盘消息则送入消息队列,非队列消息直接传递给窗口过程处理。Windows系统中的USER32.dll负责处理窗口界面处理。

       ●其他应用程序也可能向本进程发送消息。如果调用PostMessage函数向指定窗口过程发送消息,该消息将被分发到本进程的窗口消息队列。如果调用的是SendMessage函数发送的消息,则该消息会被直接发送给指定的窗口过程处理。

             

图2-10  窗口程序运行过程

举例

       一个完整的消息传递过程:

       第一步:Windows操作系统捕获键盘消息WM_KEYDOWN,并将该消息送入操作系统总消息队列。

       第二步:Windows系统将键盘消息分发给当前焦点窗口的窗口消息队列。

       第三步:主程序的消息循环GetMessage函数从消息队列中获取键盘消息。

       第四步:TranslateMessage函数将WM_KEYDOWN消息转换为WM_CHAR消息,并将WM_CHAR消息重新送入消息队列。

       第五步:DispatchMessage函数将WM_CHAR消息分发给Windows系统。

       第六步:Windows系统将WM_CHAR消息传递给窗口过程WndProc函数处理。

       第七步:WndProc函数的switch结构中处理WM_KEYDOWN消息(MessageBox窗口显示按键消息的虚拟键码),处理完之后将控制器交还给Windows操作系统。

       第八步:Windows系统将任务切换到主程序,消息循环GetMessage函数继续从消息队列中获取消息,如果消息队列中没有消息,则继续等待。

请读者写一个实例程序,测试上述消息循环过程。请单步跟踪程序执行的过程。

本文摘自编程达人系列教材《Windows API每日一练》。公众号滴水编程达人。

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

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

相关文章

OpenGauss数据库-6.表空间管理

第1关:创建表空间 gsql -d postgres -U gaussdb -W passwd123123 CREATE TABLESPACE fastspace OWNER omm relative location tablespace/tablespace_1; 第2关:修改表空间 gsql -d postgres -U gaussdb -W passwd123123 ALTER TABLESPACE fastspace R…

Gh-ost让MySQL在线表结构变更不再是难题

Gh-ost:无缝迁移,效率与安全并行- 精选真开源,释放新价值。 概览 gh-ost是由GitHub团队精心打造的在线MySQL表结构迁移工具,它以一种无需触发器的方式,实现了对数据库表结构变更的在线操作。gh-ost的设计初衷是解决现…

matlab使用教程(95)—显示地理数据

下面的示例说明了多种表示地球地貌的方法。此示例中的数据取自美国商务部海洋及大气管理局 (NOAA) 国家地理数据中心,数据通告编号为 88-MGG-02。 1.关于地貌数据 数据文件 topo.mat 包含地貌数据。topo 是海拔数据,topomap1 是海拔的颜色图。 load t…

【HarmonyOS】鸿蒙应用模块化实现

【HarmonyOS】鸿蒙应用模块化实现 一、Module的概念 Module是HarmonyOS应用的基本功能单元,包含了源代码、资源文件、第三方库及应用清单文件,每一个Module都可以独立进行编译和运行。一个HarmonyOS应用通常会包含一个或多个Module,因此&am…

【力扣高频题】003.无重复字符的最长子串

前段时间和小米的某面试官聊天。因为我一直在做 算法文章 的更新,就多聊了几句算法方面的知识。 并且在聊天过程中获得了一个“重要情报”:只要他来面试,基本上每次的算法题,都会去考察关于 子串和子序列 的问题。 的确&#xf…

【第14章】SpringBoot实战篇之多环境配置

文章目录 前言一、通用配置文件1. 定义2. 使用2.1 application.yml2.2 启动类 3. 测试 二、多环境配置文件1.定义1.1 application-local.yml1.2 application-dev.yml1.3 application-test.yml1.4 application-prod.yml 2.使用2.1 application.yml2.2 启动类 3.测试 三、多环境配…

OPPO高级项目经理曹帆受邀为第十三届中国PMO大会演讲嘉宾

全国PMO专业人士年度盛会 OPPO互联网服务系统内容生态中心高级互联网项目经理曹帆先生受邀为PMO评论主办的2024第十三届中国PMO大会演讲嘉宾,演讲议题为“加、减、乘、除——激活项目团队效能”。大会将于6月29-30日在北京举办,敬请关注! 议…

操作系统入门系列-MIT6.828(操作系统工程)学习笔记(五)---- 操作系统的组织结构(OS design)

系列文章目录 操作系统入门系列-MIT6.S081(操作系统)学习笔记(一)---- 操作系统介绍与接口示例 操作系统入门系列-MIT6.828(操作系统工程)学习笔记(二)----课程实验环境搭建&#x…

[spring] Spring MVC Thymeleaf(上)

[spring] Spring MVC & Thymeleaf(上) 本章内容主要过一下简单的 Spring MVC 的案例 简单来说,spring mvc 就是比较传统的网页开发流程,目前 boot 是可以比较轻松的配置 thymeleaf——毕竟 spring boot 内置对 thymeleaf 的…

Docker与Docker-Compose详解

1、Docker是什么? 在计算机中,虚拟化(英语: Virtualization) 是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍&…

【深度学习】—— 神经网络介绍

神经网络介绍 本系列主要是吴恩达深度学习系列视频的笔记,传送门:https://www.coursera.org/deeplearning-ai 目录 神经网络介绍神经网络的应用深度学习兴起的原因 神经网络,全称人工神经网络(Artificial Neural Network&#xf…

c# 下 ScintillaNET 显示XML信息并折叠节点

winform下显示XML信息(非WPF) 之前使用的是FastColoredTextBox,github地址如下: https://github.com/PavelTorgashov/FastColoredTextBox 但是有个问题,它支持中文,wordwraptrue,自动换行时&…

[大模型]Gemma-2B-Instruct FastApi 部署调用

环境准备 在 平台中租赁一个 3090 等 24G 显存的显卡机器,如下图所示镜像选择 PyTorch-->2.1.0-->3.10(ubuntu22.04)-->12.1。 接下来打开刚刚租用服务器的 JupyterLab,并且打开其中的终端开始环境配置、模型下载和运行演示。 pip 换源加速下载…

【IoT NTN】3GPP R18中关于各类IoT设备在NTN中的增强和扩展

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G技术研究。 博客内容主要围绕…

Nginx学习笔记(十)如何配置HTTPS协议?(公网)

目录 一、简介二、SSL 证书类型介绍三、公网 SSL 证书3.1 证书管理工具3.2 下载安装 acme.sh3.3 申请并下载证书报错1:没有指定账号报错2:DNS无法解析的域名报错3:无效的响应 404 3.4 配置 Nginx3.5 证书过期刷新 四、补充4.1 同一域名的不同…

Unity API学习之消息机制理论与应用

目录 消息机制 示例1:同一物体中不同组件之间发送消息 示例2:父与子对象之间的消息发送(BroadcastMassage) 父对象向子对象发送消息 ​编辑 子对象向父对象发送消息 消息机制 在Unity中,SendMessage 方法用于在游戏对象及其所有子对象上…

【云岚到家】-day02-2-客户管理-认证授权

【云岚到家】-day02-2-客户管理-认证授权 第二章 客户管理1 认证模块1.1 需求分析1.2 小程序认证1.2.1 测试小程序认证1.2.1.1 参考官方流程1.2.1.2 申请小程序账号1.2.1.3 创建jzo2o-customer1.2.1.4 部署前端1.2.1.5 编译运行1.2.1.6 真机调试 2 阅读代码2.1 小程序认证流程2…

虚拟机ping不通主机,但是主机可以ping通虚拟机

我在Windows10系统安装了虚拟机,设置的主机与虚拟机的连接方式是桥接,安装好后,发现虚拟机ping不通主机,但是主机可以ping通虚拟机。 我的操作是:关闭防火墙,发现虚拟机可以ping通主机了。说明是Windows10…

设计高并发秒杀系统:保障稳定性与数据一致性

✨✨谢谢大家捧场,祝屏幕前的小伙伴们每天都有好运相伴左右,一定要天天开心哦!✨✨ 🎈🎈作者主页: 喔的嘛呀🎈🎈 目录 引言 一. 系统架构设计 1. 系统架构图 二、 系统流程 三…

AI绘画工具Ideogram测评:和Midjourney不分伯仲的AI图像工具之一

Ideogram 是一款令人印象深刻的人工智能图像工具,但尽管它于去年 8 月推出并具有不可思议的文本渲染能力,但它并没有引起其他一些更引人注目的 GenAI 服务的关注。 随着该公司推出其生成式人工智能模型 1.0 版本,这种情况即将发生改变&#…