Tag Archives: windows forms

[WPF] Declare global hotkeys in XAML with NHotkey

A common requirement for desktop applications is to handle system-wide hotkeys, in order to intercept keyboard shortcuts even when they don’t have focus. Unfortunately, there is no built-in feature in the .NET framework to do it.

Of course, this is not a new issue, and there are quite a few open-source libraries that address it (e.g. VirtualInput). Most of them rely on a global system hook, which allow them to intercept all keystrokes, even the ones you’re not interested in. I used some of those libraries before, but I’m not really happy with them:

  • they’re often tied to a specific UI framework (usually Windows Forms), which makes them a bit awkward to use in another UI framework (like WPF)
  • I don’t really like the approach of intercepting all keystrokes. It usually means that you end up with a big method with lots of if/else if to decide what to do based on which keys were pressed.

A better option, in my opinion, is to listen only to the keys you’re interested in, and declare what to do for each of those. The approach used in WPF for key bindings is quite elegant:

<Window.InputBindings>
    <KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}" />
    <KeyBinding Gesture="Ctrl+Alt+Subtract" Command="{Binding DecrementCommand}" />
</Window.InputBindings>

But of course, key bindings are not global, they require that your app has focus… What if we could change that?

NHotkey is a very simple hotkey library that enables global key bindings. All you have to do is set an attached property to true on your key bindings:

<Window.InputBindings>
    <KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}"
                HotkeyManager.RegisterGlobalHotkey="True" />
    <KeyBinding Gesture="Ctrl+Alt+Subtract" Command="{Binding DecrementCommand}"
                HotkeyManager.RegisterGlobalHotkey="True" />
</Window.InputBindings>

And that’s it; the commands defined in the key bindings will now be invoked even if your app doesn’t have focus!

You can also use NHotkey from code:

HotkeyManager.Current.AddOrReplace("Increment", Key.Add, ModifierKeys.Control | ModifierKeys.Alt, OnIncrement);
HotkeyManager.Current.AddOrReplace("Decrement", Key.Subtract, ModifierKeys.Control | ModifierKeys.Alt, OnDecrement);

The library takes advantage of the RegisterHotkey function. Because it also supports Windows Forms, it is split into 3 parts, so that you don’t need to reference the WinForms assembly from a WPF app or vice versa:

  • The core library, which handles the hotkey registration itself, independently of any specific UI framework. This library is not directly usable, but is used by the other two.
  • The WinForms-specific API, which uses the Keys enumeration from System.Windows.Forms
  • The WPF-specific API, which uses the Key and ModifierKeys enumerations from System.Windows.Input, and supports global key bindings in XAML.

If you install the library from Nuget, add either the NHotkey.Wpf or the NHotkey.WindowsForms package; the core package will be added automatically.

[Windows Forms] Automatically drag and drop controls (DragMove)

Here’s a piece of code I wrote a while ago, I just thought it could be useful for WinForms developers…

In WPF, there is a very handy method to move a window with no borders : Window.DragMove. It can be used like that :

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();
        }

When you call this method, the window is moved with the mouse until the button is released. It could hardly be simpler 😉

Unfortunately, this method only exists in WPF, and a majority of developers are still working with Windows Forms. So I came up with a solution to use a similar technique in Windows Forms, with a few improvements :

  • Usable on any control, not only a window
  • No need to explicitly handle the MouseDown event
  • Form designer integration, using a IExtenderProvider

My solution consists of the following items :

  • a static DragMoveExtensions class which provides extension methods for the Control class (easily convertible to regular static methods for use with C# 2)
  • a DragMoveProvider component, which implements IExtenderProvider to add a new EnableDragMove property to controls

There are several ways to use this solution, pick the one that best suits your needs :

  • The simplest, which requires no coding at all : in design mode, drop a DragMoveProvider on the Form, and set the EnableDragMove property to true on the Form or control
  • DragMoveProvider
    DragMoveProvider
  • The closest to WPF’s DragMove : in the handler of the MouseDown event, call the DragMove extension method on the Form or control to move
  •         private void label2_MouseDown(object sender, MouseEventArgs e)
            {
                label2.DragMove();
            }
    
  • The most flexible : call the EnableDragMove extension method on the Form or control to move (no event handling needed).
  •         private void checkBox1_CheckedChanged(object sender, EventArgs e)
            {
                this.EnableDragMove(checkBox1.Checked);
            }
    

The attached Visual Studio solution contains the WinFormsDragMove library, and a test project to demonstrate the various ways to use this library. A C#2-compatible version of these projects is also included.

Download source