У меня странное поведение с 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()
который возвращает общий код ошибки (без подробностей).
Рабочее решение, которое я выложил первым, не является вариантом, я не могу распределять кучу при каждом нажатии клавиши или при нажатии мыши, я должен использовать стек.
Почему два последних терпят неудачу?
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 байтов.