MFC:以消息为基础的事件驱动系统和消息映射机制

以消息为基础的事件驱动系统和消息映射机制

(1)消息

A.What(什么是消息)

本质是一个数据结构,用于应用程序不同部分之间进行通信和交互

typedef struct tagMSG {
    HWND   hwnd;        // 接收该消息的窗口句柄
    UINT   message;     // 消息标识符(如 WM_CREATE、WM_SIZE 等)
    WPARAM wParam;      // 32 位消息的特定附加信息,确切含义依赖于消息值
    LPARAM lParam;      // 32 位消息的特定附加信息,确切含义也依赖于消息值
    DWORD  time;        // 消息创建时的时间
    POINT  pt;          // 消息创建时鼠标/光标在屏幕坐标系中的位置
} MSG;
  • hwnd:表示将要接收这个消息的窗口的句柄,也就是说谁将接收到这个消息
  • message:消息的类型标识符,指定了消息的类型,也就是说明了该消息是用来干什么的
  • wParam和lParam:这两个成员用于携带消息的附加参数,其具体含义取决于具体的消息类型
  • time:消息创建时的时间
  • pt:消息创建时鼠标/光标在屏幕坐标系中的位置

B.Which(有哪些类型的消息)

  • 窗口消息:

    与窗口内部运作有关的消息,如创建窗口(wm_create)、绘制窗口(wm_paint)、鼠标移动(wm_mousemove)、控件颜色(wm_ctlcolor)、水平滚动(wm_hscroll)等

  • 命令消息:

    当用户从菜单选中一个命令项目、按下一个快捷键或者点击工具栏上的一个按钮时,都将发送 wm_command 命令消息

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
    	ON_COMMEND(IDD_BUTTON01, OnButton1LButtonDown) 
    END_MESSAGE_MAP() 
    

    上述代码表明:当点击控件IDD_BUTTON01时,将调用函数OnButton1LButtonDown()

  • 控件通知消息:

    当窗口内的子控件发生一些事件(通常由用户输入触发),需要通知父窗口时发送的消息。通知消息只适用于标准的窗口控件,如按钮、列表框、组合框、编辑框,以及 Windows 公共控件如树状视图、列表视图等

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
    	ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeyDownList1)
    END_MESSAGE_MAP() 
    
    

    当列表控件 IDC_LIST1 发送 LVN_KEYDOWN 通知消息时,OnKeyDownList1 函数就会被调用,从而可以在该函数中进行相应的处理

  • 用户定义消息:

    step01:使用#define指令定义一个消息标识符 #define WM_MYMSG WM_USER + 8
    step02:在类声明中声明消息映射 DECLARE_MESSAGE_MAP()
    step03:在类中定义消息处理函数 afx_msg LRESULT MyMsgHandler(WPARAM wParam, LPARAM lParam);
    step04:实现消息映射

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
    	ON_MESSAGE(WM_MYMSG, OnMyMsgHandler) 
    END_MESSAGE_MAP() 
    

(2)消息队列

A.What(什么是消息队列)

本质是一个存放MSG的队列数据结构,用于存放消息的队列

B.Which(MFC中有哪些消息队列)

系统消息队列:

主要接收来自硬件设备(如鼠标、键盘等)的输入消息,然后将这些消息分配到相应应用程序的线程消息队列中

线程消息队列:

存储与该线程相关的所有消息,包括系统发送的标准 Windows 消息(如 WM_CREATE、WM_SIZE 等)、用户自定义消息以及由其他线程或进程发送给本线程的消息

例如,当用户点击鼠标时,系统会产生一个鼠标点击消息,并将其放入系统消息队列。然后,Windows 会将这个消息传递到相应应用程序的线程消息队列中。应用程序的线程在消息循环中获取到这个消息后,根据消息的类型和参数进行相应的处理,比如调用相应的窗口过程函数。

C.Why(消息队列的作用)

支持事件驱动模型:

通过消息队列,应用程序能够根据不同的消息触发相应的处理逻辑,实现对用户操作和系统事件的响应

缓冲消息:

对于短时间内大量产生的消息,消息队列起到缓冲的作用,避免消息的丢失或处理混乱。它按照先进先出的原则存储消息,保证消息处理的顺序性

跨线程通信:

不同线程之间可以通过向特定线程的消息队列发送消息来进行通信,实现线程之间的协调和数据传递

D.Who(谁管理消息队列)

在MFC中,Window操作系统统一管理着所有的消息队列,包括系统消息队列和线程消息队列。

在一个多线程的应用程序中,不同线程的消息队列由操作系统统一管理,使得每个线程能够按照其自身的逻辑和优先级来处理接收到的消息,而不会出现混乱或冲突

E.How(如何使用消息队列)

  • 向消息队列中添加消息:PostMessage()和SendMessage()

    PostMessage(),将消息放入线程的消息队列后立即返回,不等待消息被处理;
    SendMessage(),直接调用窗口的窗口过程函数来处理消息,并等待处理完成后才返回

  • 从消息队列中取消息:GetMessage()和PeekMessage()

    GetMessage(),从线程的消息队列中取出一条消息,如果消息队列中没有消息,该函数会阻塞,直到有消息可用或者收到 WM_QUIT 消息
    PeekMessage(),与 GetMessage 不同的是,如果消息队列中没有消息,它不会阻塞,而是立即返回 FALSE

    消息分发的一般步骤:循环读取消息队列中的消息,并进行

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg); //翻译消息
        DispatchMessage(&msg); //分发消息
    }
    

    TranslateMessage函数会检查传入的消息,如果发现是WM_KEYDOWN和WM_KEYUP消息的组合,且对应的键可以被键盘驱动器映射为 ASCII 字符,它就会将其转换为一条WM_CHAR消息

    DispatchMessage函数将消息分发给相应的窗口过程进行处理,因为MSG中包含消息所接收的窗口句柄

(3)消息的处理过程

外部设备或窗口内部事件产生消息,产生的消息进入线程的消息队列中,而WIndow应用程序的主函数会不断调用GetMessage函数从消息列表中获取消息,并进行消息翻译和消息转发实现消息的处理。
在这里插入图片描述

(4)消息映射机制

A.What(什么是消息映射机制)

用于将 Windows 消息与类成员函数进行关联和处理的高效机制

B.Why(消息映射机制的作用)

将这些 Windows 消息与特定的类成员函数关联起来。这样,当特定的消息被发送到窗口时,MFC 框架能够根据消息映射找到对应的处理函数,并调用它来执行相应的操作

通过消息映射机制,开发者无需直接处理复杂的 Windows 消息循环和分发逻辑,而是可以专注于编写具体的消息处理代码

C.How(如何进行消息映射)

一般而言,针对不同的消息类型,使用不同的宏进行消息映射

  • 窗口消息:

    与窗口内部运作有关的消息,如创建窗口(wm_create)、绘制窗口(wm_paint)、鼠标移动(wm_mousemove)、控件颜色(wm_ctlcolor)、水平滚动(wm_hscroll)等

  • 命令消息:

    当用户从菜单选中一个命令项目、按下一个快捷键或者点击工具栏上的一个按钮时,都将发送 wm_command 命令消息

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
    	ON_COMMEND(IDD_BUTTON01, OnButton1LButtonDown) 
    END_MESSAGE_MAP() 
    

    上述代码表明:当点击控件IDD_BUTTON01时,将调用函数OnButton1LButtonDown()

  • 控件通知消息:

    当窗口内的子控件发生一些事件(通常由用户输入触发),需要通知父窗口时发送的消息。通知消息只适用于标准的窗口控件,如按钮、列表框、组合框、编辑框,以及 Windows 公共控件如树状视图、列表视图等

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
    	ON_NOTIFY(LVN_KEYDOWN, IDC_LIST1, OnKeyDownList1)
    END_MESSAGE_MAP() 
    
    

    当列表控件 IDC_LIST1 发送 LVN_KEYDOWN 通知消息时,OnKeyDownList1 函数就会被调用,从而可以在该函数中进行相应的处理

  • 用户定义消息:

    step01:使用#define指令定义一个消息标识符 #define WM_MYMSG WM_USER + 8
    step02:在类声明中声明消息映射 DECLARE_MESSAGE_MAP()
    step03:在类中定义消息处理函数 afx_msg LRESULT MyMsgHandler(WPARAM wParam, LPARAM lParam);
    step04:实现消息映射

    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) 
    	ON_MESSAGE(WM_MYMSG, OnMyMsgHandler) 
    END_MESSAGE_MAP() 
    

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

耳机、音响UWB传输数据模组,飞睿智能低延迟、高速率超宽带uwb模块技术音频应用

在数字化浪潮席卷全球的今天,无线通信技术日新月异,其中超宽带(Ultra-Wideband,简称UWB)技术以其独特的优势,正逐步成为无线传输领域的新星。本文将深入探讨飞睿智能UWB传输数据模组在音频应用中的创新应用…

一份进销存系统指南,帮你选择合适的进销存系统

在数字化转型的浪潮中,众多企业正积极探索适合自身的转型路径。面对琳琅满目的进销存系统市场,选择一款既合适又靠谱的解决方案成为了企业的迫切需求。本文将通过深入分析与比较,为企业选择合适的进销存系统提供指南,助企业精准选…

港科夜闻 | 香港科大与阿里巴巴合作,计划成立大数据与人工智能联合实验室

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与阿里巴巴合作,计划成立大数据与人工智能联合实验室。香港科大7月19日与阿里巴巴集团签署合作备忘录,计划成立「香港科技大学–阿里巴巴大数据与人工智能联合实验室」,就生成…

了解Babel原理和手写一个babel插件

babel 简介 Babel 是一个 JavaScript 编译器,它能将 es2015,react 等低端浏览器无法识别的语言,进行编译。上图的左边代码中有箭头函数,Babel 将进行了源码转换,下面我们来看 Babel 的运行原理。 Babel 运行原理 Ba…

【视频讲解】ResNet深度学习神经网络原理及其在图像分类中的应用|附Python代码

全文链接:https://tecdat.cn/?p37134 原文出处:拓端数据部落公众号 分析师:Canglin Li 本文深入探讨了卷积层(Convolutional Layer)在深度学习框架中的核心作用与操作机制,并分析了其在特征提取、网络构…

DLMS/COSEM中公开密钥算法的使用_椭圆曲线加密法

1.概述 椭圆曲线密码涉及有限域上的椭圆曲线上的算术运算。椭圆曲线可以定义在任何数字域上(实数、整数、复数),但在密码学中,椭圆曲线最常用于有限素数域。 素数域上的椭圆曲线由一组实数(x, y)组成,满足以下等式: 方程的所有解的集合构成…

ForCloud赢战攻防 无惧突发0day漏洞 ForCloud虚实结合快速处置

攻防演练前夕,亚信安全威胁情报中心监测到一个存在于Nacos Derby中的0day漏洞,漏洞利用代码为公开状态,攻击者利用此漏洞可在目标服务器上执行任意代码。 造成的破坏程度?你可能正在使用! Nacos(Dynamic …

【MySQL】记录MySQL加载数据(LOAD DATA)

MySQL LOAD DATA 一、背景二、模拟生成用户信息三、加载到mysql表3.1、建表语句3.2 加载数据3.3、查看结果 一、背景 现在有个需求是将用户信息存入student.data文件中,在现在load到数据库中 二、模拟生成用户信息 假设用户信息,包含姓名,…

ITK-中值滤波

作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 中值滤波原理 中值滤波是一种常用的非线性滤波技术,用于去除图像中的噪声,特别是椒盐噪声和脉冲噪声。它…

15现代循环神经网络—GRU与LSTM

目录 1.门控循环单元 GRU关注一个序列门候选隐状态(candidate hidden state)隐状态总结从零开始代码实现代码简洁实现2.长短期记忆网络 LSTM门候选记忆单元(candidate memory cell)记忆单元隐状态代码1.门控循环单元 GRU GRU 是最近几年提出来的,在 LSTM 之后,是一个稍微简…

科普文:后端性能优化的实战小结

一、背景与效果 ICBU的核心沟通场景有了10年的“积累”,核心场景的界面响应耗时被拉的越来越长,也让性能优化工作提上了日程,先说结论,经过这一波前后端齐心协力的优化努力,两个核心界面90分位的数据,FCP平…

删除的视频怎样才能恢复?详尽指南

在日常生活中,我们有时会不小心删除一些重要的视频文件,或者在整理存储空间时不慎丢失了珍贵的记忆片段。这时候,我们可以通过一些数据恢复工具和技巧,找回这些被删除的视频。本文将详细介绍几种常见且有效的视频恢复方法&#xf…

C#,.NET常见算法

1.递归算法 1.1.C#递归算法计算阶乘的方法 using System;namespace C_Sharp_Example {public class Program{/// <summary>/// 阶乘&#xff1a;一个正整数的阶乘Factorial是所有小于以及等于该数的正整数的积&#xff0c;0的阶乘是1&#xff0c;n的阶乘是n&#xff0…

《操作系统》(学习笔记)(王道)

一、计算机系统概述 1.1 操作系统的基本概念 1.1.1 操作系统的概念 1.1.2 操作系统的特征 1.1.3 操作系统的目标和功能 1.2 操作系统的发展与分类 1.2.1 手工操作阶段&#xff08;此阶段无操作系统&#xff09; 1.2.2 批处理阶段&#xff08;操作系统开始出现&#xff0…

前端知识--前端访问后端技术Ajax及框架Axios

一、异步数据请求技术----Ajax Ajax是前端访问后端的技术&#xff0c;为异步请求&#xff08;不刷新页面&#xff0c;请求数据&#xff0c;只更新局部数据&#xff09;。 例如&#xff1a;在京东网站中搜索电脑&#xff0c;就会出现一些联想搜索&#xff0c;但此时页面并没有…

WEB开发-HTTP认证

1 需求 2 接口 3 示例 HTTP Authentication&#xff08;HTTP认证&#xff09;是Web服务器用来验证客户端请求的一种机制。它通常用于保护需要用户凭据&#xff08;如用户名和密码&#xff09;才能访问的资源。HTTP认证有几种不同的分类或方法&#xff0c;以下是其中一些主要的分…

手机怎么设置不同的ip地址

在数字化日益深入的今天&#xff0c;智能手机已成为我们生活、工作和学习中不可或缺的设备。然而&#xff0c;随着网络应用的广泛和深入&#xff0c;我们有时需要为手机设置不同的IP地址来满足特定需求。比如&#xff0c;避免网络限制、提高网络安全、或者进行网络测试等。本文…

解决R语言找不到系统库导致的报错

1、基本需知 1.1、系统库 系统库&#xff08;System library&#xff09;是一组预先编写和编译好的软件模块集合&#xff0c;用于支持操作系统的基本功能和提供一些常见的服务。这些库通常由操作系统或第三方开发者提供&#xff0c;并且在系统安装过程中被预装或者用户可以额…

分享 2 个 .NET EF 6 只更新某些字段的方法

前言 EF 更新数据时&#xff0c;通常情况下&#xff0c;是更新全部字段的&#xff0c;但实际业务中&#xff0c;更新全部字段的情况其实很少&#xff0c;一般都是修改其中某些字段&#xff0c;所以为了实现这个目标&#xff0c;很多程序员通常会这样作&#xff1a; 先从数据库…

数据治理之“财务一张表”

前言 信息技术的发展&#xff0c;伴随企业业务系统的纷纷建设&#xff0c;提升业务处理效率的同时&#xff0c;也将企业的整体主价值链流程分成了一段一段的业务子流程&#xff0c;很多情况下存在数据上报延迟、业务协作不顺畅、计划反馈不及时、库存积压占资多……都可以从数据…