获取接盘输入
最彻底的是钩子,能获取、拦截系统的消息,包括按键输入消息。
最常用的是重载PreTranslateMessage,只获取拦截本程序本窗口的消息。例如:
BOOL CxxxDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: 在此添加专用代码和/或调用基类
if (pMsg->message == WM_KEYDOWN)
{
switch (pMsg->wParam)
{
case VK_RETURN: // 屏蔽回车
return TRUE;
case VK_ESCAPE:
if (IDCANCEL == AfxMessageBox(_T("exit?"), MB_OKCANCEL))
return TRUE;
break;
default:
break;
}
}
return CDialogEx::PreTranslateMessage(pMsg);
}
但是一般的该重载,当本窗口不在焦点,或者焦点在editcontrol等编辑控件上时,无法拦截到。此时可以使用rawinput
rawinput使用之前需要先注册,例如:
RAWINPUTDEVICE rawinputdevice[1];
rawinputdevice[0].usUsagePage = 0x01; // Generic Desktop Controls
rawinputdevice[0].usUsage = 0x06; // Keyboard
rawinputdevice[0].dwFlags = RIDEV_INPUTSINK;// If set, this enables the caller to receive the input even when the caller is not in the foreground. Note that hwndTarget must be specified.
rawinputdevice[0].hwndTarget = AfxGetMainWnd()->m_hWnd;
BOOL ret = RegisterRawInputDevices(&rawinputdevice[0], 1, sizeof(RAWINPUTDEVICE));
if (ret == FALSE)
{
AfxMessageBox(_T("RegisterRawInputDevices return FALSE!"));
exit(0);
}
其中usUsagePage和usUsage用于指定需要获取的设备,参考:
usUsagePage
键盘、鼠标都是取0x01
usUsage
鼠标是0x02,键盘是0x06
rawinput入口
1. 重载主窗口的WM_INPUT消息获得OnRawInput
2. 重载 PreTranslateMessage,在函数里面判断pMsg->message 是否是 WM_INPUT
一般重载主窗口的WM_INPUT消息比较方便,OnRawInput的处理示例:
void CxxxDlg::OnRawInput(UINT nInputcode, HRAWINPUT hRawInput)
{
// 该功能要求使用 Windows XP 或更高版本。
// 符号 _WIN32_WINNT 必须 >= 0x0501。
// TODO: 在此添加消息处理程序代码和/或调用默认值
CString sInfo = _T("");
UINT uiSize = 0;
GetRawInputData((HRAWINPUT)hRawInput, RID_INPUT, NULL, &uiSize, sizeof(RAWINPUTHEADER));
LPBYTE pData = new BYTE[uiSize];
if (GetRawInputData((HRAWINPUT)hRawInput, RID_INPUT, pData, &uiSize, sizeof(RAWINPUTHEADER)) != uiSize) //获取消息信息
{
sInfo = _T("GetRawInputData error!\r\n");
GetDlgItem(IDC_STATIC_INFO)->SetWindowText(sInfo);
}
else
{
RAWINPUT* pRawinput = (RAWINPUT*)pData;
if (pRawinput->header.dwType == RIM_TYPEKEYBOARD)
{
// 获取设备名(设备路径),可用于区分输入的键盘
GetRawInputDeviceInfo(pRawinput->header.hDevice, RIDI_DEVICENAME, NULL, &uiSize);
TCHAR sBuffer[1024] = { 0 };
GetRawInputDeviceInfo(pRawinput->header.hDevice, RIDI_DEVICENAME, sBuffer, &uiSize);
sInfo += _T("device name:");
if (uiSize > 0)
sInfo += sBuffer;
// 获取键盘输入
if (pRawinput->data.keyboard.Message == WM_KEYDOWN)
{
TCHAR sAscii[10] = { 0 };
BYTE sKeyState[256] = { 0 };
sInfo += _T("\r\ninput:");
if (ToAscii(pRawinput->data.keyboard.VKey, pRawinput->data.keyboard.MakeCode, sKeyState, (LPWORD)sAscii, 0))
sInfo += sAscii;
AfxMessageBox(sInfo);
}
}
}
delete[] pData;
pData = nullptr;
CDialogEx::OnRawInput(nInputcode, hRawInput);
}