WPF / C# でのグローバル キーボード フック (WH_KEYBOARD_LL) の使用
提供されたコードは、WH_KEYBOARD_LL フックを使用してグローバル キーボード フックを確立することを目的としています。キーボードイベントをキャプチャして処理します。この実装は基本的に意図した機能を実現しますが、重大な問題が発生します。キーストロークが一定期間続くと、イベント処理が突然停止します。
この動作は、スレッドの問題の可能性を示唆しています。これを解決するには、フックが存在する限りコールバック デリゲートが生き続けることを確認する必要があります。
問題分析
コールバック デリゲート 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 中国語 Web サイトの他の関連記事を参照してください。