低级键盘挂钩延迟

时间:2014-07-01 00:13:27

标签: c winapi keyboard hook delay

我目前正在用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 个答案:

答案 0 :(得分:1)

  

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

documentation涵盖了该问题,其中指出:

  

在安装它的线程的上下文中调用此挂钩。通过向安装了挂钩的线程发送消息来进行调用。因此,安装钩子的线程必须有一个消息循环。

     

键盘输入可以来自本地键盘驱动程序,也可以来自对keybd_event函数的调用。如果输入来自对keybd_event的调用,则输入是#34;注入"。但是, WH_KEYBOARD_LL挂钩不会注入另一个进程。相反,上下文切换回安装钩子的进程,并在其原始上下文中调用它。然后上下文切换回生成事件的应用程序。

     

钩子过程应该在比以下注册表项中的LowLevelHooksTimeout值中指定的数据条目更短的时间内处理消息:

     

HKEY_CURRENT_USER \ Control Panel \ Desktop

     

该值以毫秒为单位。如果挂钩过程超时,系统会将消息传递给下一个挂钩。但是,在Windows 7及更高版本中,无需调用即可静默删除挂钩。应用程序无法知道钩子是否被移除。

     

注意调试挂钩无法跟踪此类低级键盘挂钩。 如果应用程序必须使用低级别挂钩,它应该在专用线程上运行挂钩,该挂钩将工作传递给工作线程,然后立即返回。

因此,您的主应用程序只会收到键盘通知,因为安装挂钩的线程可以从挂钩中轮询其消息队列中的新消息。如果您减慢轮询速度,您的通知就会延迟。

文档还说明:

  

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

所以你应该考虑改用它。