《Windows API每日一练》5.3 字符消息

2024-06-22 09:36

本文主要是介绍《Windows API每日一练》5.3 字符消息,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在本章前面讲过,通过转义状态信息可把击键消息转换为字符消息。并且提到,仅仅利用转义状态信息是不够的。还必须知道与国家/地区相关的键盘配置。其实不必担心这个问题。Windows程序主程序中的消息循环可以完美的解决这个问题。

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

{

       TranslateMessage (&msg) ;

       DispatchMessage (&msg) ;

}

这是WinMain函数中典型的消息循环。GetMessage函数从消息队列中取出下一条消息,填入msg结构的字段。DispatchMessage函数调用此消息的窗口过程。

在这两个函数之间是TranslateMessage函数,它负责把击键消息转换为字符消息。如果击键消息是WM_KEYDOWN或WM_SYSKEYDOWN,且击键和转义状态组合产生了一个字符,则TranslateMessage函数把字符消息放入应用程序的消息队列。这个字符消息将被放在按键消息之后,GetMessage函数可从消息队列中获取此字符消息。

本节必须掌握的知识点:

        四类字符消息

        消息排序

        控制字符的处理

        死字符处理

5.3.1 四类字符消息

字符消息可分为四类。      

字符

死字符

非系统字符

WM_CHAR

WM_DEADCHAR

系统字符

WM_SYSCHAR

WM_SYSDEADCHAR

WM_CHAR消息和WM_DEADCHAR消息来自于WM_KEYDOWN消息。而 WM_SYSCHAR 消息和 WM_SYSDEADCHAR 消息来自于 WM_SYSKEYDOWN 消息。

大多数情况下,Windows程序会忽略其他三种字符消息,仅处理 WM_CHAR消息。四类字符消息中的lParam参数和产生此字符码消息的按键消息(WM_KEYDOWN)中的 IParam参数是一样的(重复计数、扫描代码、扩展键标志、上下文代码、上一个键状态标志和转换状态标志)。但是,WM_CHAR消息的wParam参数不是虚拟键代码。实际上,它是ANSI或Unicode 字符码。

这些字符消息是我们遇到的将文本传递给窗口过程的第一个消息。但它们绝不是唯一 的一个。其他字符消息是将以零结束的文本串传递给窗口过程的消息。窗口过程怎么知道哪些字符数据是8位的ANSI字符编码,哪些是16位的Uincode字符编码呢?很简单,任何窗口过程,只要包含用RegisterClassA(RegisterClass的ANSI版本)注册的窗口类,就得到包含ANSI字符编码的消息。若包含用RegisterClassW(RegisterClass的宽字符版本)注册的窗口类,则得到Unicode字符编码的消息。如果你的程序用RegisteiClass注册窗口类,且Unicode标识符被定义,则你使用的实际是RegisterClassW,否则为RegisterClassA。

除非你明确地对窗口过程做了 ANSI和Unicode函数的混合编码,否则WM_CHAR消息(以及其他三个字符消息)所传递的字符码是:

(TCHAR) wParam

同一个窗口过程可能会用到两个窗口类,一个用RegisterClassA注册,另一个用 RegisterClassW注册。这意味着窗口过程会接收到用ANSI字符编码的消息和用Unicode字 符编码的消息。如果你的窗口过程需要确认是哪种字符编码,它能调用:

fUnicode = IsWindowUnicode(hvmd);

如果hwnd的窗口过程获得Unicode消息,则fUnicode变量为TRUE。这意味着此窗口基于用RegisterClassW注册的窗口类。

5.3.2 消息排序

因为 TranslateMessage 函数从 WM_KEYDOWN 和 WM_SYSKEYDOWN 消息产生字符消息,所以字符消息夹在击键消息中传给窗口过程。例如,如果CapsLock键没有锁定, 则在你按下再释放A键时,相应的窗口过程会接收以下三个消息:      

消息

按键或代码

WM_KEYDOWN

‘A’的虚拟键码(0x41)

WM_CHAR

‘a’的字符编码(0x61)

WM_KEYUP

‘A’的虚拟键码(0x41)

如果你通过以下几步输入大写字母A:按下Shift键,再按下A键,释放A键,再释放Shift 键,则窗口过程接收五个消息:

       消息

按键或代码

WM_KEYDOWN

虚拟键码VK_SHIFT(0x10)

WM_KEYDOWN

‘A’的虚拟键码(0x41)

WM_CHAR

‘A的字符编码(0x41)

WM_KEYUP

‘A’的虚拟键码(0x41)

WM_KEYUP

虚拟键码VK_SHIFT(0x10)

【注意】Shift键本身不会产生字符消息。

如果你持续按住A键,使连续击键行为产生了击键消息,则对于每一条WM_KEYDOWN 消息,可以得到一个字符消息:      

消息

按键或代码

WM_KEYDOWN

‘A’的虚拟键码(0x41)

WM_CHAR

‘a’的字符编码(0x61)

WM_KEYDOWN

‘A’的虚拟键码(0x41)

WM_CHAR

‘a’的字符编码(0x61)

WM_KEYDOWN

‘A’的虚拟键码(0x41)

WM_CHAR

‘a’的字符编码(0x61)

WM_KEYDOWN

‘A’的虚拟键码(0x41)

WM_CHAR

‘a’的字符编码(0x61)

WM_KEYUP

‘A’的虚拟键码(0x41)

如果某些WM_KEYDOWN消息的重复计数大于1,则相应的WM_CHAR消息将具有同样的重复计数值。

Ctrl键和字母键的组合会产生ASCII控制字符,范围从0x01(Ctrl-A)到0x1A(Ctrl_Z)。其中的某些控制码也可由下表中的按键产生(win10系统环境下已经不同于winNT或98):

按键

字符码

产生方法

ANSI C转义码

空格键

0x08

Ctrl-H

\b

Tab键

0x09

Ctrl-I

\t

Ctrl+回车

0x0A

Ctrl-J

\n

回车键

0x0D

Ctrl-M

\r

Esc键

0x1B

Ctrl-[

最右面一列显示了在ANSI C中定义的转义码,用来表明这些键的字符码。

Windows程序有时采用Ctrl键和字母键的组合作为菜单快捷键(我们将在第九章中讨 论)。在这种情况下,字母键不能转换为字符消息。

5.3.3 控制字符的处理

       我们按照以下的基本规则来处理击键和字符消息:如果你需要读取输入到窗口中的键 盘字符,就处理WM_CHAR消息:如果你需要读取光标键、功能键、Delete键、Insert键、 Shift键、Ctrl键和Alt键,则处理WM_KEYDOWN消息。

但是Tab键怎么办?回车键、空格键、Esc键呢?从传统意义上讲,这些键产生ASCII 控制字符,像上表中所显示的那样。但是在Windows中,它们也产生虚拟键代码。这些键应该在处理WM_CHAR消息或者在处理WM_KEYDOWN消息时被处理吗?

通常我们更偏向把Tab键、回车键、空格键 和Esc键看作控制字符,而不是虚拟键。我通常这样处理WM_CHAR消息:

case WM_CHAR:

       //其他行程式

       switch (wParam)

       {

       case '\b': // backspace

              //其他行程式

              break ;

       case '\t': // tab

              //其他行程式

              break ;

       case '\n': // linefeed

              //其他行程式

              break ;

       case '\r': // carriage return

              //其他行程式

              break ;

       default: // character codes

              //其他行程式

              break ;

       }

       return 0 ;

5.3.4 死字符处理

       Windows程序通常忽略WM_DEADCHAR和WM_SYSDEADCHAR消息,但是你应该明确地了解什么是死字符和它们怎样工作的。

在一些非美国英语的键盘上,某些键可以给字母加上音调。这些键称为“死键”,因为它们自己不产生字符。例如,当安装了德语键盘时,对于美国式键盘上的+/=键,德语键盘上相应的位置为一个死键:

未按下 Shift 键时它用于标识锐音,按下 Shift 键时则用于标识抑音。

当用户按下此键时,相应的窗口过程会接收到wParam参数等于音调本身的ASCII或 Unicode码的WM_DEADCHAR消息。若接着按下可带有音调的字母键时(例如A键),窗口 过程接收到的将是wParam参数等于带有音调的字母’a’的ANSI码的WM_CHAR消息。

因而,你的程序不必去处理WM_DEADCHAR消息,因为WM_CHAR消息已包含了程序所需要的所有信息。Windows程序甚至有内置的差错处理:如果你按下死键,接着按下不能携带音调的字母键(如‘s’键),那么窗口过程会连续接收两个WM_CHAR消息。第一个消息的wParam参数等于音调本身的ASCII码(与传递给WM_DEADCHAR消息的 wParam参数相同),第二个消息的wParam参数等于字母’s’的ASCII码。

当然,理解它的最好方式就是实际操作。你需要加载使用死键的非英语键盘,比如我前面描述过的德国键盘。你可在控制面板中通过选择【键盘】中的【语言】选项卡来设置它。然后你需要一个应用程序,它能显示程序接收的每一个键盘消息的细节。下面将要讨论的KEYVIEW1就是这样的一个程序。

这篇关于《Windows API每日一练》5.3 字符消息的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1083917

相关文章

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

通过高德api查询所有店铺地址信息

通过高德api查询所有店铺地址电话信息 需求:通过高德api查询所有店铺地址信息需求分析具体实现1、申请高德appkey2、下载types city 字典值3、具体代码调用 需求:通过高德api查询所有店铺地址信息 需求分析 查询现有高德api发现现有接口关键字搜索API服务地址: https://developer.amap.com/api/webservice/gui

DDei在线设计器-API-DDeiSheet

DDeiSheet   DDeiSheet是代表一个页签,一个页签含有一个DDeiStage用于显示图形。   DDeiSheet实例包含了一个页签的所有数据,在获取后可以通过它访问其他内容。DDeiFile中的sheets属性记录了当前文件的页签列表。   一个DDeiFile实例至少包含一个DDeiSheet实例。   本篇最后提供的示例可以在DDei文档直接预览 属性 属性名说明数

Windows中,.net framework 3.5安装

安装.net framework,目前已知2种方法,如下: 一、在MSDN下载对应的安装包,安装,这种可能无法安装成功,概率很大,不成功使用第二种方法,基本上没问题。 二、win8/8.1/10 下安装 .net framework 3.5.1: 1. 打开 win8/8.1/10 安装盘(这里指系统安装镜像文件),提取 sources\sxs 文件夹到 X:\sources\sxs (X代

Windows 可变刷新率是什么?如何开启?

在现代计算设备中,显示屏的刷新率对用户体验起着至关重要的作用。随着显示技术的不断进步,固定刷新率显示器逐渐被支持可变刷新率(Variable Refresh Rate, VRR)技术的显示器所取代。 可变刷新率定义 可变刷新率是什么?可变刷新率(VRR)是一种显示技术,它允许显示器的刷新率动态调整,以匹配显卡输出的帧率。传统的显示器通常具有固定的刷新率(如60Hz、75Hz等),这意味着显示器

API-环境对象

学习目标: 掌握环境对象 学习内容: 环境对象作用 环境对象: 指的是函数内部特殊的变量this,它代表着当前函数运行时所处的环境。 作用: 弄清楚this的指向,可以让我们代码更简洁。 函数的调用方式不同,this指代的对象也不同。【谁调用,this就是谁】是判断this指向的粗略规则。直接调用函数,其实相当于是window.函数,所以this指代window。

如何设置windows计划任务

如何设置windows计划任务 前言:在工作过程中写了一个python脚本,用于调用jira接口查询bug单数量,想要在本地定时任务执行,每天发送到钉钉群提醒,写下操作步骤用于记录。 1. 准备 Python 脚本 确保你的 Python 脚本已经保存到一个文件,比如 jira_reminder.py。 2. 创建批处理文件 为了方便任务计划程序运行 Python 脚本,创建一个批处理文

剑指offer(C++)--第一个只出现一次的字符

题目 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写). class Solution {public:int FirstNotRepeatingChar(string str) {map<char, int> mp;for(int i = 0; i < str.size(); ++i)m

消息认证码解析

1. 什么是消息认证码         消息认证码(Message Authentication Code)是一种确认完整性并进行认证的技术,取三个单词的首字母,简称为MAC。         消息认证码的输入包括任意长度的消息和一个发送者与接收者之间共享的密钥,它可以输出固定长度的数据,这个数据称为MAC值。         根据任意长度的消息输出固定长度的数据,这一点和单向散列函数很类似