首页 文章

低级键盘挂钩延迟

提问于
浏览
1

我目前正在编写一个C语言库,需要跟踪按键和释放 . 为了最佳地做到这一点,我使用low level keyboard hook调用回调函数来处理这些关键事件 .

我遇到的问题是按键似乎被推迟了 . 我的程序循环执行得越慢,关键事件到达所需的时间越长 . 我的回调函数将所有按下的键存储在一个数组中,稍后我可以从中调查它们 . 如果程序会延迟一秒钟,那么当我之后检查它时,我希望所有关键事件都在数组中 . 情况并非如此,似乎在这种情况下只存储一个事件,其余事件随后出现 .

我的回调函数如下所示,总结了不相关的部分:

static LRESULT CALLBACK llKeyProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if(nCode == HC_ACTION) {
        //The keys are processed and stored in an array to be polled by the user in the future
    }

    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

钩子附加到进程(_window-> llKeyHook是HHOOK类型):

_window->llKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, llKeyProc, NULL, 0);

关键事件在我的主循环中轮询 . 目前,每次迭代后调用Sleep(ms)限制此循环的帧速率 . 睡眠时间量由主循环的执行速度决定 . 当我将其修复为高值(如300毫秒)时,每隔300毫秒只捕获一个键,即使我在其间按下许多键也是如此 .

1 回答

  • 1

    程序循环执行得越慢,关键事件到达的时间越长 .

    该问题由documentation涵盖,其中规定:

    此挂钩在安装它的线程的上下文中调用 . 通过向安装了挂钩的线程发送消息来进行调用 . 因此,安装挂钩的线程必须具有消息循环 . 键盘输入可以来自本地键盘驱动程序,也可以来自对keybd_event函数的调用 . 如果输入来自对keybd_event的调用,则输入被“注入” . 但是,WH_KEYBOARD_LL挂钩不会注入另一个进程 . 相反,上下文切换回安装钩子的进程,并在其原始上下文中调用它 . 然后上下文切换回生成事件的应用程序 . 钩子过程应该在比以下注册表项中的LowLevelHooksTimeout值中指定的数据条目更短的时间内处理消息:HKEY_CURRENT_USER \ Control Panel \ Desktop该值以毫秒为单位 . 如果挂钩过程超时,系统会将消息传递给下一个挂钩 . 但是,在Windows 7及更高版本中,无需调用即可静默删除挂钩 . 应用程序无法知道钩子是否被移除 . 注意调试挂钩无法跟踪此类低级键盘挂钩 . 如果应用程序必须使用低级别挂钩,它应该在专用线程上运行挂钩,该挂钩将工作传递给工作线程然后立即返回 .

    因此,您的主应用程序将仅接收键盘通知,因为安装挂钩的线程可以从挂钩轮询其消息队列以获取新消息 . 如果您减慢轮询速度,您的通知会延迟 .

    文件还说明:

    在大多数应用程序需要使用低级别挂钩的情况下,它应该监视原始输入 . 这是因为原始输入可以异步监视与低级别挂钩相比更有效地针对其他线程的鼠标和键盘消息 . 有关原始输入的更多信息,请参阅原始输入 .

    所以你应该考虑使用它 .

相关问题