3. August 2011 06:55
A global keyboard hook is, as the name suggests, a means for your application to intercept (or ‘hook’) all keyboard events, not just those that occur when your application has focus. Recently I needed just such a keyboard hook for a WPF application, and wanted to be able to set focus back to my application when a particular keyboard combination was pressed. Using the C# keyboard hooking code of Stephen Toub as a starting point I created the desired system keyboard hook for WPF.
I’ve added the code to my learnwpf.com samples project on bitbucket. The key moving parts are:
keyboardhook.cs – This contains the Win32 API calls for hooking keyboard input, as well as a static method for bringing focus back to a window of your choice when the keyboard hook is triggered (which is surprisingly hard in more modern versions of windows where some measures have been taken to stop apps stealing focus from others.) This code also uses the Keyboard.Modifiers to check to see if the CTRL key has been pressed. There were some posts on-line that suggested that this doesn’t work properly when your app doesn’t have focus (which would be a major problem for what we’re doing). Fortunately it seems that this problem has been solved in .NET 4.0.
EntryPoint.cs – Instead of the WPF application starting in the ‘normal’ way through app.xaml I had to create a separate entry-point. I did this to attempt to ensure the keyboard hook is disposed off when the application exits, but you might be happy with handling the exit event and disposing of the keyboard hook there. Here we also set what key combination we want to trigger the KeyCombinationPressed event (in this case it is CTRL+F1)
App.xaml.cs - Handles the KeyCombinationPressed event raised by the keyboard hook, and uses KeyboardHook.ActivateWindow() to bring the focus back to the main window. Note that this code needs to be run on the UI thread for the application (hence the Dispatcher.Invoke).
I haven’t had much of a chance to test this on older versions of windows, so please let me know if you encounter any problems.
[Image courtesy of lovestruck]