Windows虚拟键代码

Windows virtual key codes

本文关键字:代码 虚拟 Windows      更新时间:2023-10-16

我如何实现像 std::string VirtualKeyCodeToStdString(UCHAR key)这样的函数返回虚拟键描述?

示例:输入为 VK_CAPITAL,返回值是 std::string("Caps Lock")

将VK代码转换为键文本表示的一种简单方法是:

  1. 使用MapVirtualKey将VK代码转换为扫描代码。
  2. 做一点转变以将该值转换为长时间,其中位16-23是扫描代码
  3. 使用GetKeyNameText获取键的名称。

例如:

WCHAR name[1024];
UINT scanCode = MapVirtualKeyW(VK_CAPITAL, MAPVK_VK_TO_VSC);
LONG lParamValue = (scanCode << 16);
int result = GetKeyNameTextW(lParamValue, name, 1024);
if (result > 0)
{
    std::wcout << name << endl; // Output: Caps Lock
}

如果您是为了响应WM_KEYDOWN或通过LPARAM中传递扫描代码的其他消息而执行此操作,则可以跳过前两个步骤,因为这些步骤只是在那里将VK代码按摩到GetKeyNameText的正确格式化输入中。有关GetKeyNameText的功能和第一个参数的格式的更多信息,请参见MSDN

的文档

注意:我使用了API调用上的W变体,因此您实际上需要使用std::wstring传递密钥名称,但是您可以轻松地更改它以使用A版本。另外,如果您需要通过键盘布局以获取正确的扫描代码,则可以使用MapVirtualKeyEx

没有完整的答案。谢谢大家的帮助。经过更多的研究,我编写了将virtualKey转换为std::string描述的完整功能。

* STD :: BASIC_STRING&lt;tchar>版本: *

typedef std::basic_string<TCHAR> tstring;
tstring VirtualKeyCodeToString(UCHAR virtualKey)
{
    UINT scanCode = MapVirtualKey(virtualKey, MAPVK_VK_TO_VSC);
    TCHAR szName[128];
    int result = 0;
    switch (virtualKey)
    {
        case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN:
        case VK_RCONTROL: case VK_RMENU:
        case VK_LWIN: case VK_RWIN: case VK_APPS:
        case VK_PRIOR: case VK_NEXT:
        case VK_END: case VK_HOME:
        case VK_INSERT: case VK_DELETE:
        case VK_DIVIDE:
        case VK_NUMLOCK:
            scanCode |= KF_EXTENDED;
        default:
            result = GetKeyNameText(scanCode << 16, szName, 128);
    }
    if(result == 0)
        throw std::system_error(std::error_code(GetLastError(), std::system_category()),
                                "WinAPI Error occured.");
    return szName;
}

std :: String版本:

std::string VirtualKeyCodeToString(UCHAR virtualKey)
{
    UINT scanCode = MapVirtualKey(virtualKey, MAPVK_VK_TO_VSC);
    CHAR szName[128];
    int result = 0;
    switch (virtualKey)
    {
        case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN:
        case VK_RCONTROL: case VK_RMENU:
        case VK_LWIN: case VK_RWIN: case VK_APPS:
        case VK_PRIOR: case VK_NEXT:
        case VK_END: case VK_HOME:
        case VK_INSERT: case VK_DELETE:
        case VK_DIVIDE:
        case VK_NUMLOCK:
            scanCode |= KF_EXTENDED;
        default:
            result = GetKeyNameTextA(scanCode << 16, szName, 128);
    }
    if(result == 0)
        throw std::system_error(std::error_code(GetLastError(), std::system_category()),
                                "WinAPI Error occured.");
    return szName;
}