A simple library for setting and managing global hotkeys for WPF
HotkeyUtility is compatible with .NET 5.0 (net5.0-windows) and .NET 6.0 (net6.0-windows).
You can find the package on NuGet or install it through PackageManagement:
Install-Package HotkeyUtility
There are two ways of using HotkeyUtility: through XAML with an MVVM implementation and through the codebehind.
Declaring the XAML namespace for HotkeyUtility will expose the HotkeyBinding
control that you can place under your InputBindings
:
<Window x:Name="window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hu="clr-namespace:HotkeyUtility.Controls;assembly=HotkeyUtility">
</Window>
The HotkeyBinding
control exposes the following:
- A dependency property called
Combination
(which is actually a KeyBinding) - An event called
Pressed
Here's a simple example using both in XAML:
<Window x:Name="window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hu="clr-namespace:HotkeyUtility.Controls;assembly=HotkeyUtility">
<Window.InputBindings>
<hu:HotkeyBinding Combination="Alt + Space"
Pressed="AltSpace_Pressed"/>
</Window.InputBindings>
</Window>
Now, whenever the user simultaneously presses Alt and Space, the event handler AltSpace_Pressed will be triggered.
Because Combination
is a dependency property, you can change the system-wide hotkey at runtime:
<Window x:Name="window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hu="clr-namespace:HotkeyUtility.Controls;assembly=HotkeyUtility">
<Window.InputBindings>
<hu:HotkeyBinding Combination="{Binding ElementName=window, Path=Binding}"
Pressed="AltSpace_Pressed"/>
</Window.InputBindings>
</Window>
Remember that Combination
is a KeyBinding, so when you want to programmatically change the hotkey, simply create a new KeyBinding and bind to it:
KeyBinding keyBinding = new()
{
Key = Key.Space
Modifiers = ModifierKeys.Control
};
YourBinding = keyBinding;
๐ NOTE: Do not assign a value to the ICommand parameter of the KeyBinding constructor. When the user triggers the HotkeyBinding, the ICommand will be ignored.
There is a possibility that binding to the Pressed
event of a HotkeyBinding
control will not work with certain MVVM frameworks. If this issue arises, you can attempt to circumvent it by using the VisualHotkey
control. In the following example, I'll be using the Caliburn.Micro framework.
The VisualHotkey
control isn't really a control; it has no visual properties attached to it. Therefore, you can place them anywhere since they will only affect the logical tree and not the visual tree:
<Window x:Name="window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:hu="clr-namespace:HotkeyUtility.Controls;assembly=HotkeyUtility"
xmlns:cal="http://www.caliburnproject.org">
<Grid>
<hu:VisualHotkey Combination="{Binding Combination}"
cal:Message.Attach="[Event Pressed] = [Action VisualHotkey_Pressed($this, $eventArgs)]"/>
</Grid>
</Window>
As you can see from the example above, the attached properties are the same as those for the HotkeyBinding
control.
The HotkeyManager
class employs a singleton pattern which means if you declare a Hotkey
in File1.cs, you will have access to that same Hotkey
in File2.cs.
If you would like to register a global hotkey programmatically, you can do so by:
- Invoking the
GetHotkeyManager
method in theHotkeyManager
class - Instantiating a
Hotkey
object - And by using the
TryAddHotkey
method of theHotkeyManager
class
using HotkeyUtility;
using HotkeyUtility.Input; // Contains HotkeyEventArgs
// EventHandler
public void AltSpace_Pressed(object sender, HotkeyEventArgs e)
{
Console.WriteLine("AltSpace_Pressed called");
}
HotkeyManager manager = HotkeyManager.GetHotkeyManager();
Hotkey hotkey = new(Key.Space, ModifierKeys.Alt, AltSpace_Pressed);
bool success = manager.TryAddHotkey(hotkey);
In order to remove a hotkey, use the TryRemoveHotkey
method on HotkeyManager
:
using HotkeyUtility;
// A Hotkey property
public Hotkey Hotkey { get; set; }
HotkeyManager manager = HotkeyManager.GetHotkeyManager();
bool success = manager.TryRemoveHotkey(Hotkey);
You can read and find out more in the documentation.