如何区分左右键(CTRL和ALT)?

我开始利用Win32的原始输入function来检测键盘上的所有键。 到目前为止,一切都很好! 我可以区分顶行的数字和右侧键盘的数字。 我甚至可以在左右键之间进行检测。 但是,control和alt键不会返回唯一的扫描码。 控制键返回29,并且alt键返回56。

检查这些键上的键状态的流行方法是GetAsyncKeyState 。 我已经使用VK_LCONTROLVK_RCONTROL测试了该function,但它可以工作,但这只能帮助我捕获按键事件。 我真的希望能够捕获关键事件。 很明显,API在某种程度上意识到正在按下哪个键; 我如何获得这些信息?

我目前正在从RAWKEYBOARD结构的MakeCode字段中提取扫描代码。 这给了我关于除CTRLALT之外的每个键(及其左/右对齐)的信息。 我将如何捕获关键事件(并知道它是左/右)? 是否可以只使用RAWKEYBOARD结构? 或者我是否需要制定某种解决方法?

如果你想获得足够低的水平来检测关键事件,你应该处理WM_KEYDOWN和WM_KEYUP事件:

按一个键会导致WM_KEYDOWN或WM_SYSKEYDOWN消息被放置在附加到具有键盘焦点的窗口的线程消息队列中。 释放密钥会导致WM_KEYUP或WM_SYSKEYUP消息放入队列中。

键入和按键消息通常成对出现,但如果用户按住一个足够长的键以启动键盘的自动重复function,系统会连续生成多个WM_KEYDOWN或WM_SYSKEYDOWN消息。 然后,当用户释放密钥时,它会生成单个WM_KEYUP或WM_SYSKEYUP消息。

要区分Shift,Ctrl或Alt键的左右版本,必须使用MapVirtualKey()函数或通过虚拟键消息传递的lParam中的“扩展键”位。 以下函数将为您执行该转换 – 只需从消息中传入虚拟键代码和lParam,然后您将根据需要返回左/右特定虚拟键代码:

 WPARAM MapLeftRightKeys( WPARAM vk, LPARAM lParam) { WPARAM new_vk = vk; UINT scancode = (lParam & 0x00ff0000) >> 16; int extended = (lParam & 0x01000000) != 0; switch (vk) { case VK_SHIFT: new_vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX); break; case VK_CONTROL: new_vk = extended ? VK_RCONTROL : VK_LCONTROL; break; case VK_MENU: new_vk = extended ? VK_RMENU : VK_LMENU; break; default: // not a key we map from generic to left/right specialized // just return it. new_vk = vk; break; } return new_vk; } 

如果传入的虚拟键码不是映射到左/右版本的虚拟键码,则原始键码将不加改变地传回。 因此,只要您需要区分左侧和右侧变体,就可以通过该函数运行WM_KEYDOWN / WM_KEYUP / WM_SYSKEYDOWN / WM_SYSKEYUP消息参数。

GetAsyncKeyState的文档说:

…如果设置了最重要的位,则键已关闭…

这也意味着如果它清除了MSB,那么密钥就会启动。