//Gets the resulting character from the Keyboard event. Based from the answers on https://stackoverflow.com/questions/23170259/convert-keycode-to-char-string string GetCharFromKey(GlobalKeyboardHookEventArgs e) { byte[] keyboardState = new byte[255]; bool keyboardStateStatus = DLLImports.GetKeyboardState(keyboardState); //Added this code in as the method doesn't work well without this piece of code when the application loses focus. if (Shift != ModifierKeySide.None) { keyboardState[(int)VirtualKeycodes.Shift] = 0xff; } if (Control != ModifierKeySide.None) { keyboardState[(int)VirtualKeycodes.Control] = 0xff; } if (Alt != ModifierKeySide.None) { keyboardState[(int)VirtualKeycodes.Alt] = 0xff; } if (!keyboardStateStatus) { return(""); } uint virtualKeyCode = (uint)e.KeyboardData.VirtualCode; IntPtr inputLocaleIdentifier = DLLImports.GetKeyboardLayout(0); StringBuilder result = new StringBuilder(); DLLImports.ToUnicodeEx(virtualKeyCode, (uint)e.KeyboardData.HardwareScanCode, keyboardState, result, (int)5, (uint)0, inputLocaleIdentifier); return(result.ToString()); }
//Unloads the User32 Library as this is not automatically done by GC. void DisposeUser32Handle() { if (_user32LibraryHandle != IntPtr.Zero) { if (!DLLImports.FreeLibrary(_user32LibraryHandle)) // reduces reference to library by 1. { int errorCode = Marshal.GetLastWin32Error(); throw new Win32Exception(errorCode, $"Failed to unload library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); } _user32LibraryHandle = IntPtr.Zero; } }
//Dipose our Keyhook as it is not automatically handled by the GC public void DisposeKeyHook() { if (_keyHookWindowsHandle != IntPtr.Zero) { if (!DLLImports.UnhookWindowsHookEx(_keyHookWindowsHandle)) { int errorCode = Marshal.GetLastWin32Error(); throw new Win32Exception(errorCode, $"Failed to remove keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); } _keyHookWindowsHandle = IntPtr.Zero; _keyHookProc = null; } }
//This handles the creation of Mouse Hook public void CreateMouseHook(HookProc _hookCB) { //We must not have more than one Keyboard hook for this instance of the class so we check if there's already one. If there is, we throw an error. if (_mouseHookWindowsHandle != IntPtr.Zero) throw new Exception("There's already a mouse hook instantiated! No need to create another one."); _mouseHookProc = _hookCB; // we must keep alive _hookProc, because GC is not aware about SetWindowsHookEx behaviour. _mouseHookWindowsHandle = DLLImports.SetWindowsHookEx(DLLImports.WH_MOUSE_LL, _mouseHookProc, _user32LibraryHandle, 0); if (_mouseHookWindowsHandle == IntPtr.Zero) { int errorCode = Marshal.GetLastWin32Error(); throw new Win32Exception(errorCode, $"Failed to adjust mouse hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); } }
//An overload of the DisposeKeyHook function. After disposing the hook, we unsubscribe hookProc event from the _keyHookProc instead of setting the _KeyHookProc to null. public void DisposeKeyHook(HookProc hookProc) { if (_keyHookWindowsHandle != IntPtr.Zero) { if (!DLLImports.UnhookWindowsHookEx(_keyHookWindowsHandle)) { int errorCode = Marshal.GetLastWin32Error(); throw new Win32Exception(errorCode, $"Failed to remove keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); } _keyHookWindowsHandle = IntPtr.Zero; // ReSharper disable once DelegateSubtraction _keyHookProc -= hookProc; } }
IntPtr _mouseHookWindowsHandle = IntPtr.Zero; //Int pointer to the Mouse hook //This constructor will handle the loading of the User32 Library which is the one that manages system hooks. public GlobalHookManager() { //Check if there's already an instance of this class, if there is throw an error. if (singleton != null) throw new Exception("There's already another instance of GlobalHookManager! No need to create another one."); _user32LibraryHandle = IntPtr.Zero; _user32LibraryHandle = DLLImports.LoadLibrary("User32"); if (_user32LibraryHandle == IntPtr.Zero) { int errorCode = Marshal.GetLastWin32Error(); throw new Win32Exception(errorCode, $"Failed to load library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); } singleton = this; }
public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam) { bool fEatKeyStroke = false; var wparamTyped = wParam.ToInt32(); if (Enum.IsDefined(typeof(KeyboardState), wparamTyped)) { object o = Marshal.PtrToStructure(lParam, typeof(LowLevelKeyboardInputEvent)); LowLevelKeyboardInputEvent p = (LowLevelKeyboardInputEvent)o; var eventArguments = new GlobalKeyboardHookEventArgs(p, (KeyboardState)wparamTyped); EventHandler<GlobalKeyboardHookEventArgs> handler = KeyboardPressed; handler?.Invoke(this, eventArguments); fEatKeyStroke = eventArguments.Handled; } return fEatKeyStroke ? (IntPtr)(-1) : DLLImports.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); }
private IntPtr LowLevelMouseEvent(int nCode, IntPtr wParam, IntPtr lParam) { bool fEatMouseEvent = false; var wparamTyped = wParam.ToInt32(); if (Enum.IsDefined(typeof(MouseMessages), wparamTyped)) { object o = Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); MSLLHOOKSTRUCT p = (MSLLHOOKSTRUCT)o; var eventArguments = new GlobalMouseHookEventArgs((MouseMessages)wparamTyped, p); EventHandler <GlobalMouseHookEventArgs> handler = MouseEvent; handler?.Invoke(this, eventArguments); fEatMouseEvent = eventArguments.Handled; } return(fEatMouseEvent ? (IntPtr)(-1) : DLLImports.CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam)); }