【发布时间】:2010-10-06 07:15:44
【问题描述】:
我正在尝试编写一个在按下 Shift 键时响应的应用程序,无论当前哪个应用程序具有焦点。
我用SetWindowsHookEx() 和GetKeyboardState() 试过这个,但是这两个都只在应用程序的窗口有焦点时才有效。我需要它在全球范围内工作。
我该怎么做?
【问题讨论】:
标签: c# windows windows-vista
我正在尝试编写一个在按下 Shift 键时响应的应用程序,无论当前哪个应用程序具有焦点。
我用SetWindowsHookEx() 和GetKeyboardState() 试过这个,但是这两个都只在应用程序的窗口有焦点时才有效。我需要它在全球范围内工作。
我该怎么做?
【问题讨论】:
标签: c# windows windows-vista
【讨论】:
您必须使用 SetWindowsHookEx()。只有两种类型的钩子可以在托管语言中实现,WH_KEYBOARD_LL 和 WH_MOUSE_LL。所有其他钩子都需要一个可以注入另一个进程的 DLL。无法注入托管 DLL,无法初始化 CLR。
这个blog post 有一个功能示例。
【讨论】:
如果您在 nobugz 引用的帖子中使用该技术,则需要确保委托不会被垃圾收集,例如通过在设置钩子时使用 GC.KeepAlive(_proc) ,否则在不确定的时间段后,当 delagate 被 GCed 时钩子将停止工作。
【讨论】:
提供的答案都没有帮助我解决我的问题,但我自己找到了答案。在这里。
使用SetWindowsHookEx() 和WH_KEYBOARD_LL 是正确的方法。但是,SetWindowsHookEx() 的其他参数并不直观:
dwThreadId需要为0。hMod 需要指向某个DLL。我用了
User32,这是一个总是被加载并被所有人使用的 DLL
带有 GUI 的进程。我从a CodeProject post about this 得到这个想法。因此,代码看起来有点像这样:
instance = LoadLibrary("User32");
hhook = SetWindowsHookEx(WH_KEYBOARD_LL, hookFunction, instance, 0);
文档不清楚倒数第二个参数。它说:
hMod 参数必须设置为 NULL [...] 如果挂钩过程在与当前进程关联的代码中。
它并没有说明这只适用于某些类型的钩子,但不适用于WH_KEYBOARD_LL 和WH_MOUSE_LL。
【讨论】: