当我注册 RawInput 时,我检查了函数的所有返回,一切都很好。但是,当我更新它时,它会阻塞我的第一个 CPU 内核的性能并且它不能正常工作(当我检查'M'按下按钮并让它创建一个消息框,它不仅会在我按下“M”时触发,而是在我按下任何东西或移动鼠标时触发。消息框也不会出现,还有只有哔声。)这是我用来初始化它的代码:
const ushort usageTable[] =
{
InputDeviceUsage::UsageMouse,
InputDeviceUsage::UsageKeyboard,
InputDeviceUsage::UsageGamepad,
};
const ulong flagsTable[] =
{
mouseFlags,
keyboardFlags,
hidFlags
};
const List<SystemDevices>& systemDevices = EnumerateSystemDevices();
List<String> deviceNames;
List<InputDeviceInfo> deviceInfo;
for(uint i = 0; i < systemDevices.Size(); i++)
{
deviceNames.Add(GetDeviceName(systemDevices[i].hDevice));
deviceInfo.Add(GetDeviceInfo(systemDevices[i].hDevice));
InputDevice device =
{
InputDeviceUsagePage::UsagePageHID,
usageTable[deviceInfo[i].dwType],
flagsTable[deviceInfo[i].dwType],
window
};
RegisteredDevices.Add(device);
Devices[systemDevices[i].hDevice] = CreateDevice(deviceInfo[i].dwType);
其中 List 等效于std::vector<>,这些是涉及的 typedef 和定义:
enum InputDeviceUsagePage
{
UsagePageHID = 0x01
};
enum InputDeviceUsage
{
UsageMouse = 0x02,
UsageKeyboard = 0x06,
UsageGamepad = 0x04
};
enum InputDeviceType
{
TypeMouse = RIM_TYPEMOUSE,
TypeKeyboard = RIM_TYPEKEYBOARD,
TypeHID = RIM_TYPEHID
};
enum InputDeviceChangeBehavior
{
Arrival = GIDC_ARRIVAL,
Removal = GIDC_REMOVAL
};
enum InputDeviceDataRequest
{
PreparseData = RIDI_PREPARSEDDATA,
Name = RIDI_DEVICENAME,
Info = RIDI_DEVICEINFO
};
这是更新功能:
try
{
InputData data;
RawDevice::UpdateUnbuffered(reinterpret_cast<HRAWINPUT>(lparam), &data);
DevicePtr it = Devices[data.header.hDevice];
if(it == nullptr)
{
DevicePtr newDevice = CreateDevice(data.header.dwType);
Devices.Add(data.header.hDevice, newDevice);
if(data.header.hDevice != null)
{
it = newDevice;
}
}
DevicePtr device = it;
device->Read(data);
switch(data.header.dwType)
{
case InputDeviceType::TypeMouse:
{
const RawMouse& mouse = static_cast<RawMouse&>(*device);
//TODO: add event handling here
break;
}
case InputDeviceType::TypeKeyboard:
{
const RawKeyboard& keyboard = static_cast<RawKeyboard&>(*device);
//TODO: add event handling here
break;
}
case InputDeviceType::TypeHID:
{
const RawHID& hid = static_cast<RawHID&>(*device);
//TODO: add event handling here
break;
}
default:
{
}
}
return(exit_success);
}
catch(...)
{
return(DefWindowProc(window, message, wparam, lparam));
}
因此,例如在有//TODO: 添加事件处理的地方我放了:
case InputDeviceType::TypeKeyboard:
{
const RawKeyboard& keyboard = static_cast<RawKeyboard&>(*device);
if(keyboard.KeyDown('M'))
{
MessageBox(window, L"Pressed key is 'M'", L"Input event", MB_OK);
}
break;
}
每次按下鼠标上的任何键或任何按钮时都会发出哔声,不仅是 M,而且消息框也不显示,窗口只是哔哔声。CPU 内核被加载到最大值。这是KeyDown( )功能:
const bool RawKeyboard::KeyDown(ushort key) const
{
if(_data.VKey == key && !(_data.Flags & KeyActions::KeyDown))
{
return(true);
}
{
return(false);
}
}
DevicePtr基本上是一个RawDevice*,它包含一个名称和DeviceInfo,并且从RawDevice继承RawMouse、RawKeyboard和RawHID,其中包含名为_data的RAWMOUSE、RAWKEYBOARD、RAWHID成员。
编辑:只是添加调用更新的地方:
case WM_INPUT:
{
return(_input.Update(_mainWindow.GetHandle(), message, wparam, lparam));
}
break;
EDIT2:忘记添加 ReadUnbuffered 方法:
void RawDevice::UpdateUnbuffered(const HRAWINPUT rawInput, RAWINPUT* data)
{
wint64 size(sizeof(RAWINPUT));
boolresult = GetRawInputData(rawInput, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER));
if(result == false)
{
throw RawInputException(GetLastError(), L"GetRawInputData()");
}
}