RAWINPUT странное поведение

У меня странное поведение с 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() который возвращает общий код ошибки (без подробностей).

Рабочее решение, которое я выложил первым, не является вариантом, я не могу распределять кучу при каждом нажатии клавиши или при нажатии мыши, я должен использовать стек.

Почему два последних терпят неудачу?

3

Решение

4-й параметр GetRawInputData, pcbSize, имеет две функции. При входе он указывает длину доступного буфера. При выходе он содержит длину реально используемых данных. Это довольно распространенная концепция в Windows API.

В первом случае при первом вызове входное значение не используется, и при выходе сохраняется только необходимая длина. Второй вызов работает, потому что требуемая длина все еще там.

Но во втором и третьем примере вы оставляете переменную неинициализированной, чтобы она содержала случайный мусор из стека. Видимо что-то рядом 0, что делает функцию неработоспособной. Но это только предположение, конечно, есть много способов, как это не может работать, сбой и т. Д.

Вы должны инициализировать переменную следующим образом:

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

Как примечание, будьте осторожны при использовании этого BYTE[] массив, как в вашем втором примере — некоторые Александр Беляков сделал этот полезный комментарий на странице документации API:

На Win64 GetRawInputData возвращает -1 с ERROR_NOACCESS, если буфер pData не выровнен на 8 байтов.

10

Другие решения


По вопросам рекламы [email protected]