RAWINPUT奇怪的行为

时间:2014-06-30 21:48:35

标签: c++ winapi raw-input

我对RAWINPUT有一些奇怪的行为。下面的代码如下:

case WM_INPUT:
{
     UINT rawInputSize;

     GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, nullptr, &rawInputSize, sizeof(RAWINPUTHEADER));

     LPBYTE inputBuffer = new BYTE[rawInputSize];

     GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, inputBuffer, &rawInputSize, sizeof(RAWINPUTHEADER));

     RAWINPUT* inp = (RAWINPUT*)inputBuffer;   // valid
}

但以下不起作用:

case WM_INPUT:
{
     UINT rawInputSize;
     BYTE inputBuffer[40];

     GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, inputBuffer, &rawInputSize, sizeof(RAWINPUTHEADER));        // returns error code

     RAWINPUT* inp = (RAWINPUT*)inputBuffer;
}

也:

case WM_INPUT:
{
     UINT rawInputSize;
     RAWINPUT inputBuffer;

     GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, &inputBuffer, &rawInputSize, sizeof(RAWINPUTHEADER));      // returns error code
}

两者都在GetRawInputData()失败,返回一般错误代码(没有详细信息)。

我首先发布的工作解决方案不是一个选项,我不能在每次按键或鼠标操作时进行堆分配,我必须使用堆栈。

为什么最后两次失败?

1 个答案:

答案 0 :(得分:10)

GetRawInputData的第4个参数pcbSize有两个功能。输入时,它指定可用缓冲区的长度。退出时,它包含实际使用数据的长度。这是Windows API中相当常见的概念。

在第一种情况下,第一次调用时,不使用输入值,退出时只存储所需的长度。第二个调用有效,因为所需的长度仍然存在。

但是在你的第二个和第三个例子中,你将变量保持未初始化,因此它包含来自堆栈的随机垃圾。显然是0附近的东西,这使得函数失败。但这只是猜测,当然有很多方法可以解决这个问题,崩溃等等。

你应该像这样初始化变量:

RAWINPUT inputBuffer;
UINT rawInputSize = sizeof(inputBuffer);
GetRawInputData((HRAWINPUT)(lParam), RID_INPUT, &inputBuffer, &rawInputSize, sizeof(RAWINPUTHEADER));

作为附注,在第二个示例中使用BYTE[]数组时要小心 - 一些Alexander Belyakov在API文档页面上发表了这条有用的评论:

  

在Win64上,GetRawInputData将使用ERROR_NOACCESS返回-1,除非pData缓冲区对齐8个字节。