快捷键对应表

应用程序通常定义键盘快捷方式,例如“文件打开”命令的 CTRL+O。 可以通过处理单个 WM_KEYDOWN 消息来实现键盘快捷方式,但快捷键表提供了更好的解决方案::

  • 需要更少的编码。
  • 将所有快捷方式合并到一个数据文件中。
  • 支持本地化为其他语言。
  • 允许快捷方式和菜单命令使用相同的应用程序逻辑。

快捷键表是将键盘组合(如 CTRL+O)映射到应用程序命令的数据资源。 在了解如何使用加速器表之前,需要快速介绍资源。 资源是内置于应用程序二进制 (EXE 或 DLL) 的数据 Blob。 资源存储应用程序所需的数据,例如菜单、光标、图标、图像、文本字符串或任何自定义应用程序数据。 应用程序在运行时从二进制文件加载资源数据。 若要在二进制文件中包含资源,请执行以下操作:

  1. (.rc) 文件创建资源定义。 此文件定义资源类型及其标识符。 资源定义文件可能包含对其他文件的引用。 例如,图标资源在 .rc 文件中声明,但图标图像存储在单独的文件中。
  2. 使用 Microsoft Windows 资源编译器 (RC) 将资源定义文件编译为已编译的资源 (.res) 文件。 RC 编译器随 Visual Studio 和 Windows SDK 一起提供。
  3. 将编译的资源文件链接到二进制文件。

这些步骤大致相当于代码文件的编译/链接过程。 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_COMMANDwParam 参数包含命令的数字标识符。 例如,使用前面所示的表,键笔划 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 返回零。 在这种情况下,像往常一样将窗口消息传递给 TranslateMessageDispatchMessage

下面是绘图程序处理 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 是应用程序定义的在两种模式之间切换的函数。 如何处理每个命令的详细信息显然取决于程序。

下一步

设置光标图像