Utilisation du hook de clavier global (WH_KEYBOARD_LL) dans WPF/C#
Le code fourni vise à établir un hook de clavier global en utilisant le hook WH_KEYBOARD_LL pour capturer et traiter les événements du clavier. Alors que l'implémentation atteint essentiellement la fonctionnalité prévue, un problème crucial se pose : après une période de frappes soutenues, la gestion des événements cesse brusquement.
Ce comportement suggère un problème potentiel de threading. Pour résoudre ce problème, nous devons nous assurer que le délégué de rappel reste en vie tant que le hook est en place.
Analyse du problème
Le délégué de rappel, HookCallback, est défini en ligne dans la méthode SetHook. Par conséquent, le délégué est éligible au garbage collection une fois la méthode terminée. Lorsque cela se produit, le hook cessera de recevoir des rappels, ce qui entraînera l'arrêt observé de la gestion des événements.
Solution
Pour rectifier cela, nous devons conserver une référence à le délégué et assurez-vous que sa durée de vie coïncide avec l’existence du hook. Voici le code révisé qui résout le problème :
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) } }
Dans ce code mis à jour, le délégué LowLevelKeyboardProc (rappel) est désormais un champ de la classe KeyboardListener. En conservant cette référence, nous garantissons que le délégué reste en vie et disponible pour les appels de rappel tout au long de la durée de vie du hook.
En résolvant le problème de thread de cette manière, le hook de clavier global continuera à capturer et à traiter les événements du clavier de manière fiable. , même dans des scénarios de frappes incessantes.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!