Windows 虚拟键码
Windows virtual key codes
如何实现像 std::string VirtualKeyCodeToStdString(UCHAR key)
这样的功能,其中 return 的虚拟键描述?
示例:输入为 VK_CAPITAL
,return 值为 std::string("Caps Lock")
将 VK 代码转换为密钥的文本表示的一种简单方法是:
- 使用
MapVirtualKey
将VK码转为扫码
- 进行位移以将该值转换为长整数,其中第 16-23 位是扫描码
- 使用
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
的第一个参数的函数和格式的更多信息,请参阅 documentation at MSDN
注意:我在 API 调用中使用了 W 变体,因此您实际上需要使用 std::wstring
来传递键名,但您可以更改它很容易使用 A 版本。此外,如果您需要通过键盘布局来获取正确的扫描码,您可以使用 MapVirtualKeyEx
.
没有完整的答案。谢谢大家的帮助。经过更多研究,我编写了将 virtualKey
转换为 std::string
描述的完整函数。
* std::basic_string 版本:*
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;
}
如何实现像 std::string VirtualKeyCodeToStdString(UCHAR key)
这样的功能,其中 return 的虚拟键描述?
示例:输入为 VK_CAPITAL
,return 值为 std::string("Caps Lock")
将 VK 代码转换为密钥的文本表示的一种简单方法是:
- 使用
MapVirtualKey
将VK码转为扫码 - 进行位移以将该值转换为长整数,其中第 16-23 位是扫描码
- 使用
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
的第一个参数的函数和格式的更多信息,请参阅 documentation at MSDN
注意:我在 API 调用中使用了 W 变体,因此您实际上需要使用 std::wstring
来传递键名,但您可以更改它很容易使用 A 版本。此外,如果您需要通过键盘布局来获取正确的扫描码,您可以使用 MapVirtualKeyEx
.
没有完整的答案。谢谢大家的帮助。经过更多研究,我编写了将 virtualKey
转换为 std::string
描述的完整函数。
* std::basic_string
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;
}