Learn how to attach some global hotkeys (system level accessible) for just a single key in your WinForms application.

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 !


Senior Software Engineer at Software Medico. Interested in programming since he was 14 years old, Carlos is a self-taught programmer and founder and author of most of the articles at Our Code World.

Sponsors