在 WPF / C# 中使用全局键盘钩子 (WH_KEYBOARD_LL)
此问题讨论了全局键盘钩子在重复点击后停止工作的问题
问题:
使用 WH_KEYBOARD_LL 实现的全局键盘钩子在经过一段时间的剧烈击键后停止接收按键事件。不会引发任何错误,并且无论在何处击键,都会发生错误。
可疑原因:
线程问题被怀疑是根本问题。
键盘代码示例钩子:
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using System.Windows.Input; namespace MYCOMPANYHERE.WPF.KeyboardHelper { public class KeyboardListener : IDisposable { private static IntPtr hookId = IntPtr.Zero; // Delegate to hook callback (method that will handle key events) private static InterceptKeys.LowLevelKeyboardProc hookCallback; [MethodImpl(MethodImplOptions.NoInlining)] private IntPtr HookCallback( int nCode, IntPtr wParam, IntPtr lParam) { // Handle key events here return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam); } public event RawKeyEventHandler KeyDown; public event RawKeyEventHandler KeyUp; public KeyboardListener() { // Create and assign the hook callback delegate hookCallback = (nCode, wParam, lParam) => { HookCallbackInner(nCode, wParam, lParam); return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam); }; // Set the hook using the delegate as a parameter hookId = InterceptKeys.SetHook(hookCallback); } // Remaining code not shown for brevity } internal static class InterceptKeys { public delegate IntPtr LowLevelKeyboardProc( int nCode, IntPtr wParam, IntPtr lParam); // Hook-related constants public const int WH_KEYBOARD_LL = 13; public const int WM_KEYDOWN = 0x0100; public const int WM_KEYUP = 0x0101; public static IntPtr SetHook(LowLevelKeyboardProc proc) { using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); } } // Other code not shown for brevity } // Event args and handlers for key events public delegate void RawKeyEventHandler(object sender, RawKeyEventArgs args); }
解决方案:
根据答案的建议,回调方法的委托是内联创建的,这可能导致它被垃圾收集。为了使委托保持活动状态并防止出现此问题,有必要将委托分配给成员变量。
// Assign the hook callback delegate to a member variable private InterceptKeys.LowLevelKeyboardProc hookCallback;
通过这样做,委托将在 KeyboardListener 对象的生命周期内保持活动状态。这应该可以解决键盘挂钩在一段时间后停止工作的问题。
以上是为什么我的 WPF 全局键盘挂钩 (WH_KEYBOARD_LL) 在快速击键后停止工作?的详细内容。更多信息请关注PHP中文网其他相关文章!