There are multiple ways to add HotKeys in your WinForms application like the NHotkey library, however a lot of them require to add a specifical KeyStroke (e.g Alt+ Ctrl + F8) to be executed and only work when the Form is focused, which is not the correct way to proceed when working with Global HotKeys. As a computer lover I love when everything is easy to use and use many applications for example to record the screen like camtasia, that uses an useful HotKey feature that allow you to start or pause the current recording process by simply pressing F9 or F10. Interested by such a feature I started to research until I found a nice solution to attach such HotKeys in a WinForms application and I want to share this solution with you today.
Adding Single HotKey
To proceed with the attachment of a single HotKey for a single Key, you will need to import as first step the InteropServices module at the top of your class. This will allow you to import the RegisterHotKey method of the user32.dll
of Windows. This method is the one you need to use to register your hotkey globally and according to the one that is pressed, execute some action. As first argument the method expects the window handle that the control is bound to, namely Form.Handle, then as second argument an unique ID that identifies your HotKey in your own application. This ID can be the one you want as long as it's an integer. As third argument provide the 0x0000 to indicate null as modifier and finally, the KeyCode of the Key that will trigger this HotKey when pressed. This argument is expected to be an integer, so you can check the keycode list in the official MSDN website or just force the convertion of the Keys enum of Windows Forms that is more developer friendly as the pure codes. As last step you need to override the WndProc function of the user32.dll
in your code so you can catch when a HotKey is pressed.
In this example we'll attach a MessageBox when the user presses F9 outside of our Form:
using System.Windows.Forms;
using System;
using System.Diagnostics;
using System.Threading;
using System.Drawing.Printing;
// 1. Import the InteropServices type
using System.Runtime.InteropServices;
namespace Sandbox
{
public partial class Form1 : Form
{
// 2. Import the RegisterHotKey Method
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
public Form1()
{
InitializeComponent();
// 3. Register HotKey
// Set an unique id to your Hotkey, it will be used to
// identify which hotkey was pressed in your code to execute something
int UniqueHotkeyId = 1;
// Set the Hotkey triggerer the F9 key
// Expected an integer value for F9: 0x78, but you can convert the Keys.KEY to its int value
// See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
int HotKeyCode = (int)Keys.F9;
// Register the "F9" hotkey
Boolean F9Registered = RegisterHotKey(
this.Handle, UniqueHotkeyId, 0x0000, HotKeyCode
);
// 4. Verify if the hotkey was succesfully registered, if not, show message in the console
if (F9Registered)
{
Console.WriteLine("Global Hotkey F9 was succesfully registered");
}
else
{
Console.WriteLine("Global Hotkey F9 couldn't be registered !");
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
protected override void WndProc(ref Message m)
{
// 5. Catch when a HotKey is pressed !
if (m.Msg == 0x0312)
{
int id = m.WParam.ToInt32();
// MessageBox.Show(string.Format("Hotkey #{0} pressed", id));
if (id == 1)
{
MessageBox.Show("F9 Was pressed !");
}
}
base.WndProc(ref m);
}
}
}
Adding Multiple HotKeys
In some cases as well, your application requires more than a single HotKey to trigger multiple actions. You can easily achieve this behaviour by just incrementing the ID of the HotKey for every attached HotKey. As we described before, the RegisterHotKey method expects an unique identifier as second argument that you need to provide manually. In the following example, we will add 2 global HotKeys namely F9 and F10 using as id for every key 1 and 2 respectively (increase to 3, 4, 5 etc if more HotKeys are attached). When those keys are pressed, a simple message box will be shown warning that the hotkey has been pressed:
using System.Windows.Forms;
using System;
using System.Diagnostics;
using System.Threading;
using System.Drawing.Printing;
// 1. Import the InteropServices type
using System.Runtime.InteropServices;
namespace Sandbox
{
public partial class Form1 : Form
{
// 2. Import the RegisterHotKey Method
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
public Form1()
{
InitializeComponent();
// 3. Register HotKeys
// Set an unique id to your Hotkey, it will be used to
// identify which hotkey was pressed in your code to execute something
int FirstHotkeyId = 1;
// Set the Hotkey triggerer the F9 key
// Expected an integer value for F9: 0x78, but you can convert the Keys.KEY to its int value
// See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
int FirstHotKeyKey = (int)Keys.F9;
// Register the "F9" hotkey
Boolean F9Registered = RegisterHotKey(
this.Handle, FirstHotkeyId, 0x0000, FirstHotKeyKey
);
// Repeat the same process but with F10
int SecondHotkeyId = 2;
int SecondHotKeyKey = (int)Keys.F10;
Boolean F10Registered = RegisterHotKey(
this.Handle, SecondHotkeyId, 0x0000, SecondHotKeyKey
);
// 4. Verify if both hotkeys were succesfully registered, if not, show message in the console
if (!F9Registered)
{
Console.WriteLine("Global Hotkey F9 couldn't be registered !");
}
if (!F10Registered)
{
Console.WriteLine("Global Hotkey F10 couldn't be registered !");
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
protected override void WndProc(ref Message m)
{
// 5. Catch when a HotKey is pressed !
if (m.Msg == 0x0312)
{
int id = m.WParam.ToInt32();
// MessageBox.Show(string.Format("Hotkey #{0} pressed", id));
// 6. Handle what will happen once a respective hotkey is pressed
switch (id)
{
case 1:
MessageBox.Show("F9 Key Pressed ! Do something here ... ");
break;
case 2:
MessageBox.Show("F10 Key Pressed ! Do something here ... ");
break;
}
}
base.WndProc(ref m);
}
}
}
Unregister HotKey
Probably, your HotKey may work during some stage of your application, that means if the user changes of view or something special happens in your application, this HotKey shouldn't be accessible anymore. You can unregister id by simply running the UnregisterHotKey method in the same context and setting as second argument the ID of the registered HotKey:
Note
Sometimes is just better to have a boolean flag that allows the execution of some code or not according to the status of your application instead of unregistering the HotKey. However is good to know as well how to unregister them.
using System.Windows.Forms;
using System;
using System.Diagnostics;
using System.Threading;
using System.Drawing.Printing;
// 1. Import the InteropServices type
using System.Runtime.InteropServices;
namespace Sandbox
{
public partial class Form1 : Form
{
// 2. Import the RegisterHotKey Method
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vlc);
// 3. Import the UnregisterHotKey Method
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
public Form1()
{
InitializeComponent();
// 4. Register the "F9" hotkey
int UniqueHotkeyId = 1;
int HotKeyCode = (int)Keys.F9;
Boolean F9Registered = RegisterHotKey(
this.Handle, UniqueHotkeyId, 0x0000, HotKeyCode
);
if (F9Registered)
{
Console.WriteLine("Global Hotkey F9 was succesfully registered");
}
else
{
Console.WriteLine("Global Hotkey F9 couldn't be registered !");
}
// 5. Unregister F9 HotKey
Boolean F9UnRegistered = UnregisterHotKey(this.Handle, UniqueHotkeyId);
if (F9UnRegistered)
{
Console.WriteLine("Global Hotkey F9 was succesfully UNregistered");
}
else
{
Console.WriteLine("Global Hotkey F9 couldn't be UNregistered !");
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x0312)
{
int id = m.WParam.ToInt32();
// MessageBox.Show(string.Format("Hotkey #{0} pressed", id));
if (id == 1)
{
// This will never happen because we have registered the hotkey !
MessageBox.Show("F9 Was pressed !");
}
}
base.WndProc(ref m);
}
}
}
Happy coding !