在WPF / C# 中使用全域鍵盤鉤子(WH_KEYBOARD_LL)
提供的程式碼旨在使用WH_KEYBOARD_全域鉤子建立一個全域鉤子來捕捉一個全域鉤並處理鍵盤事件。雖然實作基本上實現了其預期功能,但出現了一個關鍵問題:在持續擊鍵一段時間後,事件處理突然停止。
此行為表示有潛在的執行緒問題。為了解決這個問題,我們需要確保只要鉤子就位,回呼委託就保持活動狀態。
問題分析
回呼委託 HookCallback 是在 SetHook 方法中內聯定義。因此,一旦方法退出,委託就有資格進行垃圾回收。發生這種情況時,掛鉤將停止接收回調,從而導致觀察到事件處理終止。
解決方案
要修正此問題,我們需要保留對委託並確保其生命週期與鉤子的存在一致。以下是解決問題的修訂後的程式碼:
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; private InterceptKeys.LowLevelKeyboardProc callback; public KeyboardListener() { callback = HookCallback; hookId = InterceptKeys.SetHook(callback); } [MethodImpl(MethodImplOptions.NoInlining)] private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) { try { return HookCallbackInner(nCode, wParam, lParam); } catch { Console.WriteLine("There was some error somewhere..."); } return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam); } private IntPtr HookCallbackInner(int nCode, IntPtr wParam, IntPtr lParam) { // ... (original code here) return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam); } // ... (rest of the class) } }
在此更新的程式碼中,LowLevelKeyboardProc 委託(回呼)現在是 KeyboardListener 類別的一個欄位。透過維護此引用,我們確保委託在鉤子的整個生命週期中保持活動並可用於回調呼叫。
透過以這種方式解決線程問題,全域鍵盤鉤子將繼續可靠地捕獲和處理鍵盤事件,即使在無情的擊鍵情況下也是如此。
以上是為什麼 C# 中的全域鍵盤掛鉤在持續擊鍵後停止運作?的詳細內容。更多資訊請關注PHP中文網其他相關文章!