《Windows API每日一练》5.1 键盘基础

本节我们讲述关于键盘的一些基础知识。当我们按下一个键盘按键时,会产生一个键盘按键消息。这一点你能确定吗?假如是一个菜单快捷键消息,或者是一个子窗口控件消息呢?这就超出了本节讨论的范围,我们将在菜单和子窗口控件详细讲述。假设的确是一个按键消息,它将被送入窗口消息队列,做同步处理。在消息循环中,GetMessage函数获取到按键消息后,如果是一个字符按键消息,TranslateMessage函数会将其转化为字符消息WM_CHAR并将其送入消息队列,然后再由DispatchMessage函数继续将按键消息分发给Windows系统。如果是一个非字符按键消息,则直接由DispatchMessage函数将其分发给Windows系统。

本节必须掌握的知识点:

        忽略键盘

        键盘焦点

        队列和同步

        击键和字符

5.1.1 忽略键盘

       当我们按下键盘按键的时候会产生键盘按键消息,或者我们调用PostMessage或SendMessage函数发送键盘消息,也可能是Windows系统产生的按键消息。所有这些按键消息并不是都需要我们主动去处理的。我们只需要处理真正需要关注的一些按键消息,把一些不需要我们处理的按键消息统统交给Windows系统默认的窗口过程去处理。这些常常忽略的按键消息有以下几类:

       ■系统按键消息

通常可以忽略一些属于系统功能的按键操作。这些按键一般都包含Alt键。程序不必去监控这些按键消息,因为Windows会将按键的效果通报给程序,在默认情况下,它们会被交付给DefWindowProc函数处理。有时候我们处于某种目的也可能会拦截系统按键消息,在后面的章节中遇到了我们再详细讲述。

键盘快捷键消息

许多Windows程序用键盘快捷键来调用常用菜单项。快捷键经常是Ctrl键同功能键或 者字母键的组合(例如,Ctrl+S键用于保存一个文件)。这些键盘快捷键和程序菜单一起在程 序的资源脚本中定义,这些我们将在第九章中看到。Windows会把这些键盘快捷键转换为菜单命令消息。你不必自己去做转换,窗口过程只需要处理菜单消息就可以了。

控件消息

对话框也有键盘接口,但是程序不必在对话框活跃的时候去监视键盘。Windows会处理 键盘接口,接着Windows把击键效果的消息传送给程序。对话框包含了用于文本输入的编 辑控件。它们一般是一些小方框,用户可以输入字符串。Windows处理所有的编辑控件逻辑,并在用户输入完成后,将最终的内容传送给程序。关于对话框,将在第十章详细介绍。

编辑控件不必局限于只有单独的一行,它的位置也不必局限在对话框中。程序主窗口中的多行编辑控件可以用作一个简单的文本编辑器。(参见第八章的POPPAD程序。)另外,Windows也有专业的富文本编辑控件,可以允许你编辑和显示格式化的文本(第十一章我们会详细讲解富文本控件) 。

当你设计Windows程序时,将会发现可以使用子窗口控件来处理键盘和鼠标的输入以 便把更高层的消息传回父窗口。只要积累了足够多的这样的控件,你就不会再为处理键盘消息而烦恼了。

5.1.2 键盘焦点

       假如我们现在按下了一个键盘按键,但是桌面当前有多个窗口同时存在,那么就产生了一个问题,这个按键消息会送入到哪个窗口的消息队列呢?

       我们在第二章2.3节消息机制中讲述过,当用户按下一个按键时,产生的按键消息会被送入到Windows系统总的消息队列,然后根据按键消息所属的窗口将其送入到对应的窗口消息队列。是否还记得MSG消息结构的第一个字段就是消息所属的窗口句柄。意思是当我们按下按键的那一刻就已经确定了消息所属的窗口,而不是等到送入总消息队列后再确定所属窗口的。那么,确定消息所属窗口的依据是什么呢?就是当前具有键盘输入焦点的窗口。

       接收到这个键盘事件的窗口称为有输入焦点的窗口。输入焦点的概念和活动窗口的概 念是紧密相连的。具有输入焦点的窗口要么是活动窗口,要么是活动窗口的子孙窗口——也就是说,活动窗口的子窗口,或者是活动窗口的子窗口的子窗口,等等。

活动窗口通常是很好鉴别的。它总是最上层的窗口——也就是说,它的父窗口句柄是 NULL。如果一个活动窗口有标题栏,Windows会加亮显示其标题栏。如果活动窗口有会话边框(常见的对话框的外形)而不是标题栏,Windows会加亮显示其边框。如果活动窗口目前处于最小化状态,Windows将突出显示它在任务栏中的条目,就像一个按下的按钮似的。

如果活动窗口有子窗口,具有输入焦点的窗口可以是活动窗口,也可以是它的子孙窗口中的一个。最常见的子窗口是出现在对话框中的如下控件:按钮、单选按钮、复选框、滚动条、编辑框或列表框。子窗口自己不能成为活跃窗口。仅当它是活跃窗口的子孙窗口时,该子窗口才具有输入焦点。子窗口控件通常通过显示一个闪烁的插入符号或虚线指出输入焦点。

有时没有窗口具有输入焦点。这种情况会发生在所有程序都最小化时。但Windows仍 将发送键盘消息给活动窗口,只不过此时的消息形式不同于活动窗口没有最小化时发送的 键盘消息。

窗口过程通过捕获WM_SETFOCUS和WM_CILLFOCUS消息来确定自己的窗口是否具有输入焦点。WM_SETFOCUS表明窗口正在接受输入焦点,而WM_KILLFOCUS表明窗口正在失去输入焦点。这些消息将在本章的稍后部分详细介绍。

 

总结

1.活动窗口:桌面最上层窗口,其父窗口句柄为NULL,加亮标题栏或突出显示在任务栏。

2.焦点窗口:活动窗口的子孙窗口,通常是一个闪烁的插入符或虚线框指示输入焦点。

3.捕获WM_SETFOCUS来确定其具有输入焦点,WM_KILLFOCUS说明正失去焦点。

4.当所有程序都最小化时,没有窗口具有输入焦点,Windows仍将发送键盘消息给活动窗口。这时所有击键都产生WM_SYSKEYDOWN和WM_SYSKEYUP消息。

5.1.3 队列和同步

当用户按下和释放键盘上的一个键时,Windows和键盘设备驱动程序将硬件扫描码转 换为格式化后的消息。但是,这些消息并不立即被放入应用程序消息队列,而是由Windows 把这些消息存储在系统总消息队列中。系统消息队列是一个单独的消息队列,它被Windows 用来初步存储用户从键盘和鼠标输入的消息。仅当Windows应用程序完成了对前一个用户输入消息的处理后,Windows才从系统消息队列中取出下一条消息,并把它放入应用程序消息队列。

这是一种两步处理法,即先把消息存储在系统消息队列里,再把它们发送到应用程序消息队列。采用两步处理法的原因是需要同步。像我们刚了解的那样,被期望接收键盘输入的窗口是具有活动焦点的窗口。用户输入的速度可能快于应用程序能处理的击键动作,而一个特殊的击键可能会使焦点从一个窗口转换到另一个窗口。后续的击键也应该跟着到了另一个窗口。但如果后续的击键己经被转到了目的窗口,且被放置在了应用程序消息队列中,则它们不能被输入到另一个窗口。

图5-1 消息队列

 

总结

●两步法处理键消息:先把消息存储在系统消息队列里,再发送到应用程序消息队列里。

1.击键事件:将击键转为消息,放入系统消息队列(注意不立即放入应用程序消息队列);

2.应用程序处理完前一个输入消息,Windows从系统队列取下一条消息放入应用程序消息队列。

●两步处理法的原因——同步

因为当应用程序1接收到一个特殊的、转换窗口焦点的击键动作时,后续的击键消息也应被转移到另一个程序(如应用程序2)的队列中去。如果键盘消息不经系统队列的缓冲,当用户输入太快,而应用程序1来不及没处理完这个特殊消息时,可能后续的击键消息又被发送到应用程序1的队列中来了,从而导致错误。因此,键盘消息要先放到系统队列中,起到同步的作用。

5.1.4 击键和字符

应用程序从Windows接收的关于键盘事件的消息可分为击键和字符两种。

首先,你可以认为键盘是键的集合。键盘上仅有一个键标示为“A”。按下此键是一次击键,释放此键也认为是一次击键。同时键盘也是能产生可显示字符或者控制字符的输入设备。“A”键能产生一些不同的字符,这取决于同Ctrl、Shift、Caps Lock键的组合,通常此字符为小写字母“a”。如果Shift键被按下或者Caps Lock键被锁定,此字符就为大写字母“A”。如果Ctrl键被按下,则此字符就是Ctrl+A(它在ASCII码中有意义,但是在Windows里,就可能是一个键盘快捷键)。在一些键盘上,可能会有死字符键或者 Shift、Ctrl、Alt键与“A”键的组合。这种组合能产生带重音符号的小写字母或大写字母,例如,à、á、â、Ä、或 Å等。

对产生可显示字符的击键组合,Windows在发送击键消息的同时还发送字符消息。有些键不产生字符,如Shift键、功能键、光标移动键和特殊字符键(如Insert键和Delete键)。 对于这些键,Windows只产生击键消息。

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

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

相关文章

Jenkins+K8s实现持续集成(二)

部署前呢,要先把jenkins搭建好。 同时呢已经有了k8s的环境。 基于以上两步已经有了的情况,继续要实现jenkinsk8s持续集成,需要先准备四个文件: Dockerfile首先要准备好一个Dockerfile文件,用于构建Docker镜像的文本…

安装cuda、cudnn、Pytorch(用cuda和cudnn加速计算)

写在前面 最近几个月都在忙着毕业的事,好一阵子没写代码了。今天准备跑个demo,发现报错 AssertionError: Torch not compiled with CUDA enabled 不知道啥情况,因为之前有cuda环境,能用gpu加速,看这个报错信息应该是P…

React常用方法汇总【更新中】

文章目录 前言创建项目启动命令列表渲染父子组件传值useEffect 异步函数使用方法useEffect 异步函数清除方法控制组件显示隐藏axios 安装使用 前言 运行 react 需要先安装 node.js,具体安装步骤可以参考这篇文章 https://blog.csdn.net/weixin_43721000/article/de…

Vue65-vue-resource:ajax请求

vue-resource是vue的插件库,用vue.use(xxxx)使用插件。 1、安装 2、引入和使用 这个库,维护的频率不高了。还是建议使用:axios,vue-resource只是了解即可。

MySQL8,Navicat能登陆成功,密码却忘记了

执行成功的图: 以下为步骤:本文一共8个简单步骤。 环境:mysql8、window10、navicat11 1、打开本地电脑window10的命令窗(俗称黑窗口),windowR 2、输入regegit,回车,打开注册表 3、…

技术差异,应用场景;虚拟机可以当作云服务器吗

虚拟机和云服务器是现在市面上常见的两种计算资源提供方式,很多人把这两者看成可以相互转换或者替代的物品,实则不然,这两种资源提供方式有许多相似之处,但是也有不少区别,一篇文章教你识别两者的技术差异,…

【全文档】软件项目经理需要掌握的文档有哪些?

软件项目经理在项目管理过程中需要编写多种文档,以下是常见的十五个文档: 项目计划: 详细描述了项目的范围、时间、成本、资源、沟通计划等关键信息,是项目管理的核心文档。 需求文档: 记录了项目的业务需求、功能需求…

深入理解预处理

1.预定义符号 C语言设置了⼀些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编译的时间 __STDC__ //如果编译器遵循ANSI C&…

3. ceph-mimic版本部署

ceph-mimic版本部署 一、ceph-mimic版本部署1、环境规划2、系统基础环境准备2.1 关闭防火墙、SELinux2.2 确保所有主机时间同步2.3 所有主机ssh免密2.4 添加所有主机解析 3、配置ceph软件仓库4、安装ceph-deploy工具5、ceph集群初始化6、所有ceph集群节点安装相关软件7、客户端…

LeetCode322.零钱兑换(一)

LeetCode刷题记录 文章目录 📜题目描述💡解题思路⌨C代码 📜题目描述 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。…

项目监督与控制

1.什么是项目过程度量?其方法有哪些? 项目过程度量是一种对项目执行过程中的活动和性能进行量化测量的方法。它涉及到收集、分析和解释项目数据,以便更好地理解项目的进度、质量和效率。过程度量的目的是提供关于项目健康状况的客观信息&…

代码随想录第28天|回溯算法

491. 非递减子序列 思路: 不可以排序, 否则会改变元素的顺序对收获的结果有要求, num.size() > 2, 且 num[i - 1] < num[i]需要进行去重, 不能使用排序后的方法去重每一层可用 unordered_set 去重组合问题, for 遍历需要标记起始位置 bug: 一定要先判断元素是否重复, …

使用CAPL创建系统变量之sysDefineNamespace

目录 0 前言 1 使用CAPL创建系统变量 0 前言 最近在项目中发现可以通过CAPL来创建系统变量&#xff0c;这样方法在一定程度上提高了代码的统一性和测试的便利性。想要加入HIL自动化测试群的小伙伴欢迎评论区留言或私信&#xff0c;让我们一起进步&#xff01; 1 使用CAPL创建…

染发膏粪大肠菌群检测 化妆品毒理学检测 功效测试

染发膏中粪大肠菌群的检测 染发膏中的粪大肠菌群检测是为了确保产品的卫生安全&#xff0c;因为粪大肠菌群通常存在于动物的肠道中&#xff0c;它们的存在可能表明产品受到了外部环境的污染。根据国家标准GB/T 7918.3-1987&#xff0c;对化妆品中粪大肠菌群的检测方法进行了规范…

【html】爱心跳动动画:CSS魔法背后的故事

效果展示&#xff1a; 代码介绍&#xff1a; 爱心跳动动画&#xff1a;CSS魔法背后的故事 在前端开发中&#xff0c;CSS不仅仅是一种用于控制网页样式的工具&#xff0c;它也是一种表达创意和想象力的艺术手段。今天&#xff0c;我要为大家介绍一段使用CSS实现的爱心跳动动画…

【bug】配置SpringCloudAlibaba AI的maven依赖问题

问题描述 尝鲜alibaba的ai模块&#xff0c;maven依赖一直报找不到包&#xff0c;报错如下 Unresolved dependency: org.springframework.ai:spring-ai-core:jar:0.8.1原因分析&#xff1a; 由于是按照官方文档配置的&#xff0c;所以检查了很多遍maven配置&#xff0c;加上去…

【Docker】——安装镜像和创建容器,详解镜像和Dockerfile

前言 在此记录一下docker的镜像和容器的相关注意事项 前提条件&#xff1a;已安装Docker、显卡驱动等基础配置 1. 安装镜像 网上有太多的教程&#xff0c;但是都没说如何下载官方的镜像&#xff0c;在这里记录一下&#xff0c;使用docker安装官方的镜像 Docker Hub的官方链…

内外网映射访问内网服务器

如果本地有公网ip&#xff0c;比如连接的宽带有公网ip&#xff0c;可以直接通过路由配置转发就行了&#xff0c;如果本地没有公网ip&#xff0c;那就需要通过下面这种方式来访问内网服务器了。 1&#xff1a;首先内网服务器需要连接外网&#xff0c;可以通过网线或者WiFi都可以…

小林图解系统-二.硬件结构 2.4CPU缓存一致性

CPU Cache的数据写入 CPU和内存的访问性能越差越大&#xff0c;于是在CPU内部嵌入CPU Cache(高速缓存)。 CPU Cache由Cache Line组成&#xff0c;Cache Line由头标志Tag数据块Data Block组成。 如果数据写入Cache&#xff0c;内存和Cache相对应的数据将不同&#xff0c;需要…

Redis-五种数据结构之列表(ziplist、quicklist)

列表 文章目录 列表压缩列表-ziplistziplist 定义级联更新 快速列表-quicklistquicklistNode 定义quicklist 定义quicklist常用操作其他操作quicklist 相对于普通链表优点quick应用场景在redis 中使用quicklist 列表数据类型可以存储一组按插入顺序排序的字符串&#xff0c;他很…