应用程序通常定义键盘快捷方式,例如“文件打开”命令的 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,其中定义了这些常量。
- 关键字 VIRTKEY 意味着第一个条目是虚拟键代码。 另一个选项是使用 ASCII 字符。
- 可选修饰符:ALT、CONTROL 或 SHIFT。
如果将 ASCII 字符用于快捷方式,则小写字符将不同于大写字符。 (例如,键入“a”可能会调用与键入“A”不同的命令。这可能会使用户感到困惑,因此通常最好对快捷方式使用虚拟密钥代码,而不是 ASCII 字符。
加载加速器表
必须先加载加速器表的资源,然后程序才能使用它。 若要加载加速器表,请调用 LoadAccelerators 函数。
HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCEL1));
在输入消息循环之前调用此函数。 第一个参数是模块的句柄。 (此参数传递给 WinMain 函数。有关详细信息,请参阅 WinMain:应用程序入口点。)第二个参数是资源标识符。 该函数将返回资源的句柄。 回想一下,句柄是一种不透明类型,引用由系统管理的对象。 如果函数失败,它将返回 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
是由应用程序定义的函数,用于在两种模式之间切换。 如何处理每个命令的详细信息显然取决于程序。
下一个