Skip to content

giosali/HotkeyUtility

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

50 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

HotkeyUtility

A simple library for setting and managing global hotkeys for WPF

NuGet Version Target Framework

CI Workflow License

Table of Contents

Requirements

HotkeyUtility is compatible with .NET 5.0 (net5.0-windows) and .NET 6.0 (net6.0-windows).

Installation

You can find the package on NuGet or install it through PackageManagement:

Install-Package HotkeyUtility

Usage

There are two ways of using HotkeyUtility: through XAML with an MVVM implementation and through the codebehind.

XAML

The HotkeyBinding Control

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.

Changing the Hotkey at Runtime

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.

VisualHotkey

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.

Codebehind

The HotkeyManager Class

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.

Adding a Hotkey

If you would like to register a global hotkey programmatically, you can do so by:

  • Invoking the GetHotkeyManager method in the HotkeyManager class
  • Instantiating a Hotkey object
  • And by using the TryAddHotkey method of the HotkeyManager 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);

Removing a 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);

Documentation

You can read and find out more in the documentation.