windows 快捷键概述(Windows Accelerators)---严格来说,应该称为键盘加速器

https://docs.microsoft.com/zh-cn/windows/desktop/menurc/about-keyboard-accelerators

本文翻译介绍windows 热键,我们通常所说的热键/快捷键,微软文档中为“Keyboard Accelerators”。翻译中使用“快捷键”表示这一概念。

题外话,https://social.technet.microsoft.com/Forums/scriptcenter/en-US/94867ee8-c03e-42d5-90cb-d34f153fb587/show-registered-keyboard-shortcuts-hotkeys?forum=ITCG 该链接中提到两个概念keyboard shortcuts 和 keyboard Accelerators ,前一个针对系统全局范围的快捷键,后一个对应的应用软件中的快捷键,感觉两者之间还是有却别的(Accelerators  也包括了应用程序特有的和系统全局范围的),应该分别翻译为“按键快捷键”、“按键加速器”,但我们通常不习惯称呼“按键加速器”。

快捷键和菜单类似,都给用户提供了一种访问应用程序的功能集的机会。通常,用户通过阅读软件的菜单来了解应用的功能集,之后,用户可以通过快捷键来更加高效的使用应用的功能。快捷键使得可以更加快速、准确的使用应用所提供的功能。应用程序至少应该为常见的命令生成快捷键,另外,一般快捷键是对应菜单命令的,但是,也可以只存在快捷键而没有菜单(比如esc通常可以退出当前窗口,这种常见的功能不必有菜单但可以有快捷键)。

文章包含以下内容:

  1. 快捷键表
  2. 快捷键表的创建
  3. 快捷键按键分配
  4. 快捷键和菜单
  5. UI 状态

快捷键表

一个快捷键项包含一个ACCEL 结构的数组,每个ACCEL 结构定义了一个独立的快捷键。每个ACCEL 包括以下的信息:

typedef struct tagACCEL { BYTE fVirt; WORD key; WORD cmd; WORD fVirt; DWORD cmd; } ACCEL, *LPACCEL;

  • 快捷键的键组合信息
  • 快捷键的ID
  • 各种标志,其中包含一个标志,指示当快捷点被使用的时候时候展示可视化的反馈,即,如果有对应的菜单项的话,是否使其高亮显示。

为了处理线程的快捷键击键消息,开发人员必须在线程的消息队列的消息循环中调用TranslateAccelerator 函数。该函数监控消息队列中的键盘输入,检查按键组合是否匹配了快捷键表中的任何一项。如果找到,它将翻译键盘输入(WM_KEYUP 和 WM_KEYDOWN 消息)为WM_COMMAND 或 WM_SYSCOMMAND 消息,并将此消息发送给特定的窗口的窗口处理消息。如下图所示:

keyboard accelerator processing model

WM_COMMAND 包含了该快捷键的ID,窗口处理程序检查该ID以确定消息源,并恰当的处理该消息。

快捷键表存在两个等级。系统包含的唯一的,系统范围的应用于所有应用的快捷键表。应用程序不可以修改系统的快捷键表。

系统也包含针对每个应用程序的快捷键表。一个应用程序可以定义任意数量的它自身使用的快捷键。一个唯一的32-bit 句柄标志每个表。对于特定的线程来说,只能有一个快捷键表是同时活动的。传给TranslateAccelator 函数的句柄决定了当前线程中活动的快捷键表是哪个。线程的快捷键表随时可能改变,因为传递给TranslateAccelerator 函数的快捷键表的ID 是不确定的。

快捷键表的创建

为应用程序添加快捷键需要几个步骤:

  1. 使用资源编辑器来创建快捷键表资源,并添加它们到应用程序的PE 文件中
  2. 程序运行时,LoadAccelerators 函数将被调用以加载快捷键表到内存中,并取得快捷键表的句柄

另外,通过传递ACCEL 结构数组给CreateAcceleratorTable 函数在程序运行时创建快捷键表。这个方法支持用户定义快捷键。系统自动销毁快捷键表,但是当应用程序不需要快捷键表时,可以通过调用DestroyAcceleratorTable 函数来显式销毁快捷键表。

已经存在的快捷键是可以被复制和修改的。通过CopyAcceleratorTable 函数来复制快捷键表,如果被拷贝的表被修改,CreateAcceleratorTable 函数被调用以生成新的快捷键表句柄。

快捷键按键分配

使用ASCII 字符码或者虚拟键码来标识快捷键,ASCII字符使得快捷键大小写敏感。但要考虑capslk 按键以及shift 按键对大小写的影响。

通常,快捷键不需要大小写敏感,所以,大部分应用程序使用虚拟键来标识快捷键。

不要讲快捷键和菜单的助记符搞混了。

如果一个应用程序的快捷键和系统范围的快捷键冲突了,应用程序的快捷键表覆盖系统的快捷键表,当且仅当当前的线程上下文是应用程序的上下文。应该尽量避免这种冲突。系统范围的快捷键表如下:

快捷键和菜单

使用快捷键或选择一个菜单项都将导致系统给对应的窗口发送一个WM_COMMAND 或 WM_SYSCOMMOND 消息。WM_COMMAND 消息包含一个ID,标识了消息源,如果是快捷键表,是快捷键表的ID,如果是菜单,标识了菜单项。因为快捷键提供了选择某个菜单的捷径,应用程序经常为快捷键和对应的菜单使用同样的ID。尽管如此,WM_COMMAOND 消息包含一个标记,区别快捷键和菜单,以防万一需要区别这两者。WM_SYSCOMMAND 消息不包含这个标志。

ID 决定了快捷键生成的消息是WM_COMMAND 还是 WM_SYSCOMMAND。如果ID和系统菜单的一个项值相同,生成WM_SYSCOMMAND。否则,生成WM_COMMAND。

如果快捷键对应的菜单被禁用,不产生WM_COMMAND 或 WM_SYSCOMMAND 消息。另外,如果对应的窗口被最小化了,快捷键将不会产生命令消息。

当用户使用了有对应菜单项的快捷键,窗口处理程序接收到WM_INITMENU和 WM_INITMENUPOPUP消息,就像用户选择了菜单项。https://docs.microsoft.com/zh-cn/windows/desktop/menurc/menus 指示了如何处理该消息。

菜单项对应的快捷键应该被包含在菜单项的文本中。

UI 状态

Windows 使得应用程序可以在它的UI上隐藏或者显示各种功能,这些状态被称为UI 状态,包含下面的设置:

  1. 聚焦指示(如当前输入位置等)
  2. 敲击快捷键(通过在控制标签打下划线)

窗口可以发送消息一请求UI状态的改变,可以解析UI 状态,可以强制他的子窗口为特定的状态,分别使用了下面的消息:

默认,所有的顶层窗口的子窗口与创建它们的父窗口的UI 状态是相同的。

系统在窗口创建的时候正确的初始化其状态,所有的子空间继承这个状态。窗口创建后,系统监控用户按键,如果UI状态设置被隐藏,此时用户使用按键,系统更新UI状态,比如,如果用户按tab 键以移动焦点到下一个控件,系统调用WM_CHANGEUISTATE以指示这个聚焦的改变。如果用户按Alt 键,系统调用WM_CHANGEUISTATE 使得按键快捷键可见。

如果一个控件支持它包含的UI 状态的改变,他可以更新自己的UI 状态。控件可以调用WM_QUERYUISTATE 以解析和缓存初始的UI 状态。无论何时控件接收到WM_UPDATEUISTATE消息,它可以更新自己的UI并发送UI_CHANGEUISTATE消息给他的父窗口。每个窗口将包持续的发送该消息给父窗口指导它到了顶层窗口。顶层窗口发送WM_UPDATEUISTATE 消息到窗口树种的窗口们。如果窗口不传输WM_CHANGEUISTATE消息,消息将不到达顶层窗口,UI 状态也得不到更新。

猜你喜欢

转载自blog.csdn.net/qq_18218335/article/details/81206550