0

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

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

问题是此处RAWKEYBOARD描述的结构中的标志不能正常工作。

当我按下右控制键时,RI_KEY_E0设置为左键版本,当我按下左控制键时,既不设置RI_KEY_E0也不RI_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;
}
4

3 回答 3

1

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

检查 lParam 参数的第 24 位。

于 2012-05-18T12:42:00.823 回答
0

WM_KEYDOWN并在按下任一控制键时WM_KEYUP发送给您。要了解是否按下了右手控制键,请阅读MSDN 文档中所述的第24 位。第 24 位是这样描述的:VK_CONTROLwParamlParam

指示键是否为扩展键,例如出现在增强的 101 或 102 键键盘上的右手 ALT 和 CTRL 键。如果是扩展键,则值为 1;否则为 0。

于 2012-05-18T12:48:08.663 回答
0

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

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

为了纠正这个问题,可以使用RAWKEYBOARD::VKeyRAWKEYBOARD::MakeCode成员。不同的键以不同的方式区分不同的面:

  • 对于 shift 键,使用MapVirtualKey和传递RAWKEYBOARD::MakeCodeandMAPVK_VSC_TO_VK_EX作为参数重新分配,以及
  • 对于基于RI_KEY_E0标志的 control 和 alt 键映射(key.VKey = key.Flags & RI_KEY_E0 ? VK_RCONTROL : VK_LCONTROL例如)。

您希望从数字键盘获得的值取决于您是否将 NUMLK 视为打开或关闭。

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

于 2013-08-20T16:19:00.070 回答