WM_INPUT有缺陷

时间:2012-05-18 12:31:37

标签: c++ winapi input window

我想抓住按键发送到我的窗口以存储每个键的状态,并区分键的左右实例,如WM_LCONTROLWM_RCONTROL

由于WM_KEYUP/DOWN不提供此功能所以我转移到原始输入,我需要处理WM_INPUT

问题是来自RAWKEYBOARD结构的标记here描述不起作用。

当我按下右控制键时,设置RI_KEY_E0,用于左侧版本 键,当我按左控制键时,RI_KEY_E0RI_KEY_E1都没有设置。 alt键执行类似,但我可以解决此问题,因为左仍然提供右键的不同标志。

但是对于左右移位键,没有设置任何标志来区分左侧版本和右侧版本,因此我无法对它们做任何事情。

WM_INPUT到达时给出的虚拟密钥代码不区分左右键,并且在扫描代码上使用MapVirtualKey也不起作用。

原始投入的这种非正统行为是怎么回事?

一些代码:

注册:

RAWINPUTDEVICE rid;
rid.usUsagePage=0x01;
rid.usUsage=0x06;
rid.dwFlags=0; // I also tried RIDEV_APPKEYS,RIDEV_NOHOTKEYS,RIDEV_NOLEGACY, none fixed the problem
rid.hwndTarget=hwnd;
if(!RegisterRawInputDevices(&rid,1,sizeof(RAWINPUTDEVICE)))
    ExitError("Failed to register raw input device",true); //displays error and exits

处理WM_INPUT:

case WM_INPUT:
{    
    RAWINPUT rw;
    UINT sz=sizeof(rw);
    u_char vk; //used to make code shorter
    USHORT flag; //used to make code shorter

    if(!GetRawInputData((HRAWINPUT)lparam,RID_INPUT,&rw,&sz,sizeof(RAWINPUTHEADER)))
        break;

    vk=rw.data.keyboard.VKey;
    flag=rw.data.keyboard.Flags;

    ...Process flags and save the actual key pressed in vk...

    keys[vk]=!(flag&RI_KEY_BREAK); //save key's state
    break;
}

3 个答案:

答案 0 :(得分:1)

WM_KEYDOWN/-UP会提供您想要的信息,您只需阅读MSDN中的说明。

检查lParam参数的第24位。

答案 1 :(得分:0)

当按下任一控制键时,

WM_KEYDOWNWM_KEYUP会在VK_CONTROL中向您发送wParam。要确定是否按下了右侧控制键,请阅读lParam的第24位,如MSDN documentation中所述。第24位描述如下:

  

指示密钥是否为扩展密钥,例如增强型101键或102键键盘上显示的右侧ALT和CTRL键。如果它是扩展密钥,则值为1;否则,它是0。

答案 2 :(得分:0)

RAWKEYBORAD的文档错误。常量RI_KEY_E0RI_KEY_E1不适用于 left right 版本的键;相反,它们适用于扫描码扩展。

转储到RAWKEYBOARD::VKey的虚拟键值指的是VK_SHIFTVK_CONTROLVK_MENU等通用值。

要更正此问题,可以使用RAWKEYBOARD::VKeyRAWKEYBOARD::MakeCode成员。不同的键以不同的方式区分不同的方面:

  • 使用MapVirtualKey重新分配轮班键并将RAWKEYBOARD::MakeCodeMAPVK_VSC_TO_VK_EX作为参数传递,
  • 对于基于RI_KEY_E0标志的控制和alt键映射(例如key.VKey = key.Flags & RI_KEY_E0 ? VK_RCONTROL : VK_LCONTROL)。

您想要从小键盘中获得的值取决于您是将NUMLK视为打开还是关闭。

我和你有同样的困惑,我仍在学习键盘如何传输数据,但我发现 Molecular Musings 上的this博客文章特别有帮助。这种方法背后的原因可以在this帖子中找到。