【发布时间】:2017-06-20 17:58:54
【问题描述】:
在继承自 CView 的 PreTranslateMessage(MSG *pMsg) 内的 MFC 应用程序中,我有这个:
if (pMsg->message == WM_KEYDOWN) ...
WM_KEYDOWN 中的字段记录在 here 中。虚拟键VK_的值在pMsg->wParam和pMsg->lParam中包含几个字段,其中16-23位是键盘扫描码。
所以在我的代码中我使用:
const int virtualKey = pMsg->wParam;
const int hardwareScanCode = (pMsg->lParam >> 16) & 0x00ff; // bits 16-23
例如,在我的非美国键盘上,当我按下“#”字符时,我得到以下信息:
virtualKey == 0xde --> VK_OEM_7 "Used for miscellaneous characters; it can vary by keyboard."
hardwareScanCode == 0x29 (41 decimal)
我想“捕获”或以不同方式处理的字符是 ASCII“#”,0x23(十进制 35)。
我的问题
无论语言或键盘布局如何,如何翻译WM_KEYDOWN 信息以获得可以比较的内容?我需要识别# 键,用户是使用标准美式键盘还是其他键盘。
例如,我一直在研究以下函数,例如:
MapVirtualKey(virtualkey, MAPVK_VSC_TO_VK);
// previous line is useless, the key VK_OEM_7 doesn't map to anything without the scan code
ToAscii(virtualKey, hardwareScanCode, nullptr, &word, 0);
// previous line returns zero, and zero is written to `word`
编辑:
长话短说:在美国键盘上,SHIFT+3 = #,而在法语键盘上 SHIFT+3 = /。所以我不想看单独的键,而是想了解角色。
在处理 WM_KEYDOWN 时,如何翻译 lParam 和 wParam(“键”)以找出键盘和 Windows 将要生成的字符?
【问题讨论】:
-
这很令人困惑,因为这个问题将 keys 与 characters 混为一谈,所以我不太明白你在追求哪个。
-
我明白你为什么感到困惑了。在法语-加拿大键盘上,有一个专门用于“#”字符的键。就像'A'字符有一个键等等。所以键和字符是一回事。我忘记了在不是这种情况的美国键盘上。
-
如果您想知道字符,您需要观看 WM_CHAR(或相关)消息。但我不认为那些经过预翻译。相反,它们是由 TranslateMessage 生成的。
-
我需要在预翻译中捕获它,以便我可以使用某些键盘事件并防止它们到达底层窗口。
-
如果它是一个特定的窗口(或窗口类),您可以对窗口进行子类化以拦截 WM_CHAR 并传递其他所有内容。
标签: windows winapi mfc keyboard-events scancodes