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

时间:2011-04-15 19:13:54

标签: c++ c winapi input keyboard

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

检查这些密钥上的关键状态的常用方法是GetAsyncKeyState。我已使用VK_LCONTROLVK_RCONTROL测试了该功能,但它确实有效,但这只能帮助我捕获按键事件。我真的希望能够捕获关键事件。很明显,API在某种程度上意识到正在按下哪个键;我如何获得这些信息?

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

2 个答案:

答案 0 :(得分:6)

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

  

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

     

通常是加密和关键信息   成对出现,但如果用户持有   按下一个键足够长的时间来启动   键盘的自动重复功能,   系统生成一些   WM_KEYDOWN或WM_SYSKEYDOWN消息   连续。然后它生成一个单一的   WM_KEYUP或WM_SYSKEYUP消息时   用户释放密钥。

要区分Shift,Ctrl或Alt键的左右版本,必须使用随虚拟键消息传递的lParam中的MapVirtualKey()函数或“扩展键”位。以下函数将为您执行该转换 - 只需从消息中传入虚拟键代码和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消息参数。

答案 1 :(得分:1)

GetAsyncKeyState的文档说:

  

......如果最重要的是   设置,关键是关闭...

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