using System; using System.Diagnostics; using System.Runtime.InteropServices; namespace ScreenConnect; public class LowLevelKeyboardHooker : IDisposable { private WindowsNative.HOOKPROC keyboardProc; private IntPtr hookHandle; public event EventHandler HookCalled; public LowLevelKeyboardHooker() { IntPtr hMod = default(IntPtr); using (Process process = Process.GetCurrentProcess()) { using ProcessModule processModule = process.MainModule; hMod = WindowsNative.GetModuleHandle(processModule.ModuleName); } keyboardProc = LowLevelKeyboardProc; hookHandle = WindowsNative.SetWindowsHookEx(WindowsNative.WH.KEYBOARD_LL, keyboardProc, hMod, 0u); } public void Dispose() { if (hookHandle != IntPtr.Zero) { WindowsNative.UnhookWindowsHookEx(hookHandle); } } protected virtual bool OnHookCalled(WindowsNative.KBDLLHOOKSTRUCT keyInfo) { LowLevelKeyboardHookCalledEventArgs e = new LowLevelKeyboardHookCalledEventArgs { KeyInfo = keyInfo }; this.RaiseEvent(HookCalled, e); return e.ShouldEat; } private IntPtr LowLevelKeyboardProc(int code, IntPtr wParam, IntPtr lParam) { WindowsNative.WM wM = (WindowsNative.WM)(int)wParam; if (wM == WindowsNative.WM.KEYDOWN || wM == WindowsNative.WM.KEYUP || wM == WindowsNative.WM.SYSKEYDOWN || wM == WindowsNative.WM.SYSKEYUP) { WindowsNative.KBDLLHOOKSTRUCT keyInfo = (WindowsNative.KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(WindowsNative.KBDLLHOOKSTRUCT)); if (OnHookCalled(keyInfo)) { return (IntPtr)1; } } return WindowsNative.CallNextHookEx(IntPtr.Zero, code, wParam, lParam); } }