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

news2024/11/15 5:10:04

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

(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.coloradmin.cn/o/1942643.html

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

相关文章

二分查找的实现

前提&#xff1a;数组是有序的 #include <stdio.h>//作用&#xff1a;利用二分查找法查找数据 //返回值&#xff1a;数据在数组中的索引 //找到了&#xff1a;真实索引 没找到&#xff1a;返回-1 int search(int arr[], int num, int len) {//查找范围int min 0;int …

DC系列靶场---DC 2靶场的渗透测试(一)

信息收集 Nmap扫描 nmap -sV -p- -sC -T4 172.30.1.141 域名解析 echo 172.30.1.141 dc-2 >> /etc/hosts 目录枚举 gobuster dir -u http://172.30.1.141 -w work/lab/CTF/ATT_CK_01/SecLists-master/Discovery/Web-Content/big.txt -x .php,.rar,.html,.zip -t 20 -b…

将代码转换为图表的 6大工具

文章目录 将代码转换为图表的 6大工具 - 前言1、[Diagrams](https://diagrams.mingrammer.com/) - Python2、[Go-Diagrams](https://github.com/blushft/go-diagrams) - Go3、[Mermaid ](https://mermaid.js.org/) - JavaScript4、[PlantUML](https://plantuml.com/zh/) - Java…

VUE之---slot插槽

什么是插槽 slot 【插槽】&#xff0c; 是 Vue 的内容分发机制&#xff0c; 组件内部的模板引擎使用slot 元素作为承载分发内容的出口。slot 是子组件的一个模板标签元素&#xff0c; 而这一个标签元素是否显示&#xff0c; 以及怎么显示是由父组件决定的。 VUE中slot【插槽】…

Druid【基础 01】是什么+主要特点+设计原则+架构+数据结构(简单入门Druid)

Druid入门 1. 是什么2. 主要特点3. 三个设计原则4. Architecture 架构5. 数据结构5.1 DataSource 结构5.2 Segment 结构 Druid 非中文官网&#xff0c;内容不少且介绍的挺详细的&#xff0c;需要英文阅读能力或者翻译工具进行辅助。 1. 是什么 先看看官网怎么说&#xff1a; A…

C#初级——基础语法

前言 学习Unity游戏编程开发会使用到两种语言&#xff0c;一种是C#&#xff0c;另一种是Javascript。有学习C语言基础和想学unity游戏开发的萌新一般都推荐学习C#基础编程&#xff0c;以此来快速上手unity的学习。 本次学习使用到的工具为&#xff1a;VS2022 环境安装 首先&a…

对比预测编码表示学习

对比预测编码表示学习 引言 文章主要提出如下几点&#xff1a;首先将高维数据压缩到更加紧凑的潜在嵌入&#xff08;latent embdding&#xff09;空间&#xff0c;在这个空间中条件预测更容易被建模。第二&#xff0c;在这个潜在空间中使用自回归模型&#xff0c;以对未来的多…

PingCAP 王琦智:下一代 RAG,tidb.ai 使用知识图谱增强 RAG 能力

导读 随着 ChatGPT 的流行&#xff0c;LLMs&#xff08;大语言模型&#xff09;再次进入人们的视野。然而&#xff0c;在处理特定领域查询时&#xff0c;大模型生成的内容往往存在信息滞后和准确性不足的问题。如何让 RAG 和向量搜索技术在实际应用中更好地满足企业需求&#…

【C++11】智能指针深度详解(什么是智能指针?为什么需要智能指针?如何使用智能指针?)

目录 一、前言 二、 智能指针的引入 --- 内存泄露 &#x1f4a2;什么是内存泄漏&#xff1f;&#x1f4a2; &#x1f4a2;内存泄漏有那些危害&#xff1f;&#x1f4a2; &#x1f4a2;内存泄漏的原因&#xff1f;&#x1f4a2; &#x1f4a2;解决内存泄漏的方法 &#x…

go-kratos 学习笔记(3) google buf 管理proto

google buf 管理proto&#xff0c;以及从新归档文件的目录结构 什么是 BSR&#xff1f; BSR 将 Protobuf 文件作为版本化模块进行存储和管理&#xff0c;以便个人和组织可以轻松使用和发布他们的 API。 BSR 带有可浏览的 UI、依赖项管理、API 验证、版本控制、生成的文档以及…

手把手教你CrossOver 24.0.0 for Mac 破解版安装激活2024图文教程

兔八哥爱分享要和大家分享的是一款可以让我们直接在Mac上安装和运行Windows软件和游戏的软件——CrossOver。兔八哥爱分享这次带来的是24.0.0 测试版本。 CrossOver已支持相当多的Windows应用&#xff0c;如Office、AutoCAD、Windows Media Player 9、Photoshop、Dreamweaver、…

Java并发的笔记

打算记录自己的学习情况&#xff0c;尽量不摆烂&#xff0c;另外一件事要有始有终&#xff0c;要弄完 如果多个线程处理同一个变量&#xff0c;读跟写都保证不了 2024.7.22》》》》》》》》》》》》 2.1.1volatile的实现原理 volatile不会引起线程上下文的切换和调度 一致性更…

《0基础》学习Python——第十八讲__爬虫/<1>

一、什么是爬虫 爬虫是一种网络数据抓取的技术。通过编写程序&#xff08;通常使用Python&#xff09;&#xff0c;爬虫可以自动化地访问网页&#xff0c;解析网页内容并提取出所需的数据。爬虫可以用于各种用途&#xff0c;如搜索引擎的索引&#xff0c;数据分析和挖掘&#x…

【中项】系统集成项目管理工程师-第4章 信息系统架构-4.7安全架构

前言&#xff1a;系统集成项目管理工程师专业&#xff0c;现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试&#xff0c;全称为“全国计算机与软件专业技术资格&#xff08;水平&#xff09;考试”&…

软件测试---测试需求分析

课程目标 什么是软件测试需求 软件测试需求的必要性 如何对软件测试需求进行分析&#xff08;重点&#xff09; 课程补充 灰度测试&#xff08;基于功能&#xff09;&#xff1a;先发布部分功能&#xff0c;然后看用户的反馈&#xff0c;再去发布另外一部分的功能更新。 A/B测…

Qt绘制指南针(仪表盘绘制封装使用)

指南针是一种用来确定方向的工具。它由一个磁针制成&#xff0c;其一端被磁化&#xff0c;可以自由旋转。当放置在水平面上时&#xff0c;磁针会指向地球的磁北极。通过观察磁针的指向&#xff0c;我们可以确定地理北方的方向。本示例是在Qt中绘制一个指南针&#xff0c;通过继…

基于springboot+vue+uniapp的宿舍管理系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

C++学习笔记02-结构基础(问题-解答自查版)

前言 以下问题以Q&A形式记录&#xff0c;基本上都是笔者在初学一轮后&#xff0c;掌握不牢或者频繁忘记的点 Q&A的形式有助于学习过程中时刻关注自己的输入与输出关系&#xff0c;也适合做查漏补缺和复盘。 本文对读者可以用作自查&#xff0c;答案在后面&#xff0…

Git的使用教程

仓库分区 Git本地有三个工作区域:工作目录&#xff08;Working Directory&#xff09;,暂存区&#xff08;Stage/Index&#xff09;&#xff0c;资源库&#xff08;Repository或Git Directory&#xff09;。如果再加上远程的git仓库&#xff08;Remove Directory&#xff09;就…

SAP PP 物料主数据字段状态控制

参考 https://zhuanlan.zhihu.com/p/452823415 物料主数据里面的状态 由 1、行业 2、工厂 3、物料类型 4、事务代码 5、采购相关字段 6、客制 优先级 隐藏->显示->必输->可选