WPF / C# でのグローバル キーボード フック (WH_KEYBOARD_LL) の使用
キーボード リスナーが一定期間後に動作しなくなる問題に対処するには問題の原因を理解することが重要です。問題の根本は、コールバック デリゲートの作成方法と SetHook メソッド内での使用方法にあります。
次のコード スニペットは問題を示しています。
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); } }
このコードでは、コールバックデリゲートは SetHook メソッド呼び出し内でインラインで作成され、proc パラメーターに割り当てられます。ただし、このデリゲートはクラスまたはインスタンス内の他の変数やプロパティに割り当てられていません。つまり、デリゲートがガベージ コレクションされるのを妨げる参照がないことを意味します。
デリゲートがガベージ コレクションされると、関数ポインターSetWindowsHookEx に渡されたコールバックは無効になり、コールバックを呼び出すことができなくなります。これが、リスナーがしばらくすると動作を停止する理由です。
この問題を解決するには、フックが存在する限り、デリゲートへの参照を有効にしておく必要があります。これは、クラスまたはインスタンス内のフィールドまたはプロパティにデリゲートを割り当てることで実現できます。例:
private static LowLevelKeyboardProc _proc; public static IntPtr SetHook(LowLevelKeyboardProc proc) { _proc = proc; using (Process curProcess = Process.GetCurrentProcess()) using (ProcessModule curModule = curProcess.MainModule) { return SetWindowsHookEx(WH_KEYBOARD_LL, _proc, GetModuleHandle(curModule.ModuleName), 0); } }
デリゲートを _proc フィールドに割り当てることで、SetHook メソッドが呼び出されている限りデリゲートが存続することが保証されます。これにより、ガベージ コレクターがデリゲートを収集することがなくなり、コールバックが呼び出され続けることが保証されます。
以上がWPF C# グローバル キーボード フックが機能しなくなるのはなぜですか? どのように修正すればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。