快捷键对应表
应用程序通常定义键盘快捷方式,例如“文件打开”命令的 CTRL+O。 可以通过处理单个 WM_KEYDOWN 消息来实现键盘快捷方式,但快捷键表提供了更好的解决方案::
- 需要更少的编码。
- 将所有快捷方式合并到一个数据文件中。
- 支持本地化为其他语言。
- 允许快捷方式和菜单命令使用相同的应用程序逻辑。
快捷键表是将键盘组合(如 CTRL+O)映射到应用程序命令的数据资源。 在了解如何使用加速器表之前,需要快速介绍资源。 资源是内置于应用程序二进制 (EXE 或 DLL) 的数据 Blob。 资源存储应用程序所需的数据,例如菜单、光标、图标、图像、文本字符串或任何自定义应用程序数据。 应用程序在运行时从二进制文件加载资源数据。 若要在二进制文件中包含资源,请执行以下操作:
- (.rc) 文件创建资源定义。 此文件定义资源类型及其标识符。 资源定义文件可能包含对其他文件的引用。 例如,图标资源在 .rc 文件中声明,但图标图像存储在单独的文件中。
- 使用 Microsoft Windows 资源编译器 (RC) 将资源定义文件编译为已编译的资源 (.res) 文件。 RC 编译器随 Visual Studio 和 Windows SDK 一起提供。
- 将编译的资源文件链接到二进制文件。
这些步骤大致相当于代码文件的编译/链接过程。 Visual Studio 提供了一组资源编辑器,可用于轻松创建和修改资源。 (这些工具在 Visual Studio.) 的 Express 版本中不可用,但 .rc 文件只是一个文本文件,语法记录在 MSDN 上,因此可以使用任何文本编辑器创建 .rc 文件。 有关详细信息,请参阅 关于资源文件。
定义快捷键表
快捷键表是键盘快捷方式表。 每个快捷方式由以下各项定义:
- 数字标识符。 此数字标识将由快捷方式调用的应用程序命令。
- 快捷方式的 ASCII 字符或虚拟键代码。
- 可选修改键:Alt、Shift 或 Ctrl。
快捷键表本身有一个数字标识符,用于标识应用程序资源列表中的表。 让我们为简单的绘图程序创建加速键表。 此程序将具有两种模式:绘制模式和选择模式。 在绘图模式下,用户可以绘制形状。 在选择模式下,用户可以选择形状。 对于此程序,我们要定义以下键盘快捷方式。
快捷键 | 命令 |
---|---|
Ctrl+M | 在模式之间切换。 |
F1 | 切换到绘图模式。 |
F2 | 切换到选择模式。 |
首先,为表和应用程序命令定义数字标识符。 这些值是任意的。 可以通过在头文件中定义标识符来为标识符分配符号常量。 例如:
#define IDR_ACCEL1 101
#define ID_TOGGLE_MODE 40002
#define ID_DRAW_MODE 40003
#define ID_SELECT_MODE 40004
在此示例中, 值 IDR_ACCEL1
标识快捷键表,接下来的三个常量定义应用程序命令。 按照约定,定义资源常量的头文件通常命名为 resource.h。 下一个列表显示资源定义文件。
#include "resource.h"
IDR_ACCEL1 ACCELERATORS
{
0x4D, ID_TOGGLE_MODE, VIRTKEY, CONTROL // ctrl-M
0x70, ID_DRAW_MODE, VIRTKEY // F1
0x71, ID_SELECT_MODE, VIRTKEY // F2
}
加速键快捷方式在大括号中定义。 每个快捷方式包含以下条目。
- 调用快捷方式的虚拟键代码或 ASCII 字符。
- 应用程序命令。 请注意,示例中使用了符号常量。 资源定义文件包括 resource.h,其中定义了这些常量。
- 关键字 (KEYWORD) VIRTKEY 表示第一个条目是虚拟键代码。 另一个选项是使用 ASCII 字符。
- 可选修饰符:ALT、CONTROL 或 SHIFT。
如果将 ASCII 字符用于快捷方式,则小写字符将与大写字符不同的快捷方式。 (例如,键入“a”可能会调用与键入“A”不同的命令。) 这可能会使用户感到困惑,因此通常最好使用虚拟键代码而不是 ASCII 字符作为快捷方式。
加载加速器表
必须先加载快捷键表的资源,程序才能使用它。 若要加载加速器表,请调用 LoadAccelerators 函数。
HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));
在进入消息循环之前调用此函数。 第一个参数是模块的句柄。 (此参数将传递给 WinMain 函数。有关详细信息,请参阅 WinMain:Application Entry Point.) 第二个参数是资源标识符。 函数返回资源的句柄。 回想一下,句柄是引用由系统管理的对象的不透明类型。 如果函数失败,则返回 NULL。
可以通过调用 DestroyAcceleratorTable 来释放快捷键表。 但是,当程序退出时,系统会自动释放该表,因此仅当将一个表替换为另一个表时,才需要调用此函数。 创建 用户可编辑加速器主题中有一个有趣的示例。
将键笔划转换为命令
快捷键表的工作原理是将笔划转换为 WM_COMMAND 消息。
WM_COMMAND 的 wParam 参数包含命令的数字标识符。 例如,使用前面所示的表,键笔划 Ctrl+M 将转换为值为 ID_TOGGLE_MODE
的WM_COMMAND消息。 为此,请将消息循环更改为以下内容:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(win.Window(), hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
此代码在消息循环中添加对 TranslateAccelerator 函数的调用。 TranslateAccelerator 函数检查每个窗口消息,查找向下键消息。 如果用户按下快捷键表中列出的其中一个组合键, TranslateAccelerator 会将 WM_COMMAND 消息发送到窗口。 函数通过直接调用窗口过程发送 WM_COMMAND 。 当 TranslateAccelerator 成功转换键笔划时,该函数将返回一个非零值,这意味着应跳过消息的正常处理。 否则, TranslateAccelerator 返回零。 在这种情况下,像往常一样将窗口消息传递给 TranslateMessage 和 DispatchMessage。
下面是绘图程序处理 WM_COMMAND 消息的方式:
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DRAW_MODE:
SetMode(DrawMode);
break;
case ID_SELECT_MODE:
SetMode(SelectMode);
break;
case ID_TOGGLE_MODE:
if (mode == DrawMode)
{
SetMode(SelectMode);
}
else
{
SetMode(DrawMode);
}
break;
}
return 0;
此代码假定 SetMode
是应用程序定义的在两种模式之间切换的函数。 如何处理每个命令的详细信息显然取决于程序。
下一步