Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / C#
Article

Simple steps to enable Hotkey and ShortcutInput user control

Rate me:
Please Sign up or sign in to vote.
4.52/5 (33 votes)
21 Jan 2004CPOL6 min read 172.6K   6.2K   64   26
Follow these simple steps to enable a hotkey for your Windows Form. Use this user control to allow the user to specify their desired hotkey.

Introduction

I wanted to include a Hotkey facility in one of my tray applications - which I had been putting off for some time, since I didn't want to get dirty with Win32 API calls etc. When I finally tackled it, it proved to be a lot simpler than I thought. I also chucked together a little user control that I hope some of you will find useful. The control allows the user to specify their desired Hotkey, and has useful properties that will get you Hotkey-ing in no time.

Background

This article [^] is an alternative way to implement Hotkeys - it's a helper class which is totally separate to your form. However, it uses the Shortcut enum, as opposed to the Keys enum (which supports 3 simultaneous modifiers). Also I'm hoping to show that you can easily add Hotkeys to your form yourself.

Adding a Hotkey to your form in a 4 simple steps

  1. Import the Interop namespace, since we have to call a Win32 API function to register the Hotkey.
    C#
    using System.Runtime.InteropServices;
  2. Add these static external methods to your form (or a separate class if you prefer).
    C#
    [DllImport("user32.dll")]
    public static extern bool RegisterHotKey(IntPtr hWnd,
      int id,int fsModifiers,int vlc);
    [DllImport("user32.dll")]
    public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
  3. Listen for the Hotkey windows message, by examining all windows messages passed to the form. Replace this.Activate() with your desired response to the Hotkey (eg: show the form, if you have a tray application).
    C#
    protected override void WndProc(ref Message m)
    {
       if (m.Msg == 0x0312)
          this.Activate();
       base.WndProc(ref m);
    }
  4. Now register your Hotkey. The first argument is the handle to this form (window). The second is, as far as I can make out, a code to identify your Hotkey. The third argument specifies which modifier keys to register (just add up the numbers in the comments depending on your desired combination). The fourth argument is the character code of the alphanumeric key (or even other keys). If you are specifying a letter, it must be uppercase.
    C#
    // Alt = 1, Ctrl = 2, Shift = 4, Win = 8
    FrmStartup.RegisterHotKey(this.Handle, 
      this.GetType().GetHashCode(), 3, (int)'J');

Note that the RegisterHotKey Win32 API call returns true/false depending on the success of the call. It will fail if another application has already registered that Hotkey, or if you register the same Hotkey twice for your application.

Unregistering a Hotkey

Assuming you followed the steps above, just call:

C#
FrmStartup.UnregisterHotKey(this.Handle, this.GetType().GetHashCode());

No need to specify the key combination, that's what the identifier is for. As far as I can tell, you don't strictly need to unregister the Hotkey when your application closes. There was no difference in my testing, but to be safe you probably should.

The ShortcutInput user control

This user control provides some useful functionality not just for allowing the user to specify their desired shortcut key, but also getting the modifier total and character code (required for registering a Hotkey) from a Keys enumeration instance. The handy thing about the Keys enum is that it is essentially just an integer, which can easily be saved in a config or text file.

Features

  • Allows combination of 3 modifier keys (Shift, Control, Alt)
  • You can set the minimum number of modifiers you require the use to check, and then access the IsValid property to validate.
  • Just set the Keys property and the checkboxes and dropdownlist are automatically selected. Now since the Keys enum is basically an integer, that just leaves you to store/retrieve that number for a file and register the Hotkey.

Limitations

  • The main limitation is that this control does not allow the user to actually press their key combination to specify it. This input type is offered by a lot of applications, and is something I may attempt in the future.
  • Character can only be alphanumeric (i.e. no support for multimedia keys etc)
  • No Win key support. There are a few reasons for this: 1) The Keys enum has an LWin & RWin but they are not modifier keys and so cannot be combined with other keys. 2) usability: even though most keyboards now have this key, the labeling is not standardized (for example mine says "Start"), and you would have to explain to the user what the Win key is. 3) three modifiers are sufficient.
  • I coded a pretty rudimentary method to extract the character code from a Keys enum instance. I wouldn't go so far as to call it a "hack" since it will work fine for alphanumeric keys - which is all I needed for this control. But theoretically I should be using bit masks etc. to separate the modifiers and the key character properly.

Using ShortcutInput user control

Add the user control to your toolbox like you normally would. If you're not sure how to do this, here is one way: copy the user control source file to your application, rebuild. Right-click the toolbox, select Add/Remove Items. Browse to your just-rebuilt assembly, and select it. The user control should then appear at the bottom of your toolbox.

When you load your form you'll need to register your Hotkey, since it does not persist after you close your application.

C#
int val = GetHotkeySetting();
Keys k = (Keys) val;
bool success = FrmMain.RegisterHotKey(this.Handle, 
               this.GetType().GetHashCode(),
               ShortcutInput.Win32ModifiersFromKeys(k),
               ShortcutInput.CharCodeFromKeys(k));

val would be the integer you stored in your settings file. Then you'll notice the two static methods of ShortcutInput that are called to return the modifiers total separately from the character code.

Now when the user needs to change their Hotkey, on your settings form, place the control using the designer as you normally would, then at runtime your form would have to set the Keys property as follows:

C#
int val = GetSerializedInteger();
Keys k = (Keys) val;
ShortcutInput1.Keys = k;

Setting the Keys property will then select the correct checkboxes and the dropdownlist.

Then when the user clicks Apply, you'll need to register the new Hotkey based on the user's selection:

C#
bool success = FrmMain.RegisterHotKey(this.Handle, 
              this.GetType().GetHashCode(),
              ShortcutInput1.Win32Modifiers,
              ShortcutInput1.CharCode);

I think the properties accessed here are self-explanatory.

Then I'll just demonstrate using the minimum modifiers validation, so you can require the user to, say, select at least 2 modifiers:

C#
ShortcutInput1.MinModifiers = 2;

Then check the validity:

C#
bool valid = ShortcutInput1.IsValid;

For completeness, I'll list the remaining 3 minor properties. They return whether each modifier was selected.

C#
bool one = ShortcutInput1.Shift;
bool two = ShortcutInput1.Control;
bool three = ShortcutInput1.Alt;

Some notes about the Keys enum

As I mentioned I used a rudimentary solution to get the character codes from a Keys enum instance. The .NET documentation says: "The four right digits of a key value contain modifier bits for the SHIFT, CONTROL, and ALT keys". Well since the ALT value is 262144, and is more than 4 digits, this is a bit confusing. The conclusion that I've come to (but haven't investigated) is that the first 2 bytes hold the modifiers, and the last 2 bytes hold the key character. Can someone confirm whether this is the case?

So what I did was use the ToString() return value to get the character code. For example: "A, Alt" = A key, "D1, Shift, Control" = digit 1 key etc. Here are some values of key combinations. The first column is the C# code, the second is the ToString() value, and the third is the integer value.

C#
Keys.A | Keys.Alt  // -  A, Alt  -  262209
Keys.D1 | Keys.Control | Keys.Shift  // -  D1, Shift, Control  -  196657
Keys.LWin | Keys.Alt  // -  LWin, Alt  -  262235
Keys.A | Keys.B  // -  C  -  67
Keys.Z | Keys.LWin  // -  LWin  -  91
Keys.ControlKey  // -  ControlKey  -  17
Keys.BrowserBack  // -  BrowserBack  -  166

Line 4 shows that you cannot combine character keys. Line 5 shows that the Windows Key is not a modifier key

Points of Interest

This is my first article on CP. Feedback & comments are welcome.

History

  • 21 Jan 2004 - Original article

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Australia Australia
Ash is a C# developer (MCAD) with a background developing e-commerce and content management solutions. His current role includes working with VOIP systems, integration and maintenance of business and billing apps. His personal projects include the ScrollingGrid web control to enable cross-browser freeze-header 2-way scrolling of DataGrids. His other interests include travel, cinema, Squash, photography, Muay Thai.

Comments and Discussions

 
GeneralMy vote of 5 Pin
codertuhin30-Jan-13 4:12
codertuhin30-Jan-13 4:12 
QuestionA bit limited? Pin
doctorwho60131-Mar-12 10:51
doctorwho60131-Mar-12 10:51 
AnswerRe: A bit limited? Pin
Ashley van Gerven2-Apr-12 17:08
Ashley van Gerven2-Apr-12 17:08 
GeneralMy vote of 5 Pin
SecretKingdom6-Feb-12 3:18
SecretKingdom6-Feb-12 3:18 
QuestionRegistered Hot key ovveride other application hot key. Pin
ksrdhilip7-Dec-11 0:32
professionalksrdhilip7-Dec-11 0:32 
Hi,

I registered the hot key "Ctrl + s" for my application to show and hide a panel, it's working fine on my application.
But my problem is when i opened my application and opened a notepad typed something and tried to save the notepad, it is not saving and in the back side of the notepad my application's, the panel is showing and hiding.

Thanks and Regards
Dhilip.R
QuestionGreat article - thank you! Pin
jclark239b96-Dec-11 15:37
jclark239b96-Dec-11 15:37 
NewsDisplay HotKey chars [modified] Pin
xJOx12-Aug-11 15:50
xJOx12-Aug-11 15:50 
GeneralMy vote of 5 Pin
Hanson Cheng18-Mar-11 8:25
Hanson Cheng18-Mar-11 8:25 
QuestionSimple steps to enable Hotkey Pin
RichardMarx16-Feb-11 5:12
RichardMarx16-Feb-11 5:12 
GeneralMy vote of 4 Pin
RusselSSC27-Jan-11 12:36
RusselSSC27-Jan-11 12:36 
RantThis is not that good Pin
Nicolai Schönberg15-Nov-09 23:38
Nicolai Schönberg15-Nov-09 23:38 
Questionbug? Pin
aldo hexosa28-Jul-09 23:21
professionalaldo hexosa28-Jul-09 23:21 
AnswerRe: bug? Pin
Ashley van Gerven29-Jul-09 16:36
Ashley van Gerven29-Jul-09 16:36 
GeneralThank you Pin
M_B_A13-Jun-09 17:29
M_B_A13-Jun-09 17:29 
Generalmessage still not send to actual activate windows Pin
troiszyzy1-Jul-08 2:08
troiszyzy1-Jul-08 2:08 
GeneralThanks for the Register code Pin
hannahb21-Aug-07 6:55
hannahb21-Aug-07 6:55 
GeneralCharCodeFromKeys not work for me Pin
upsb sgdf17-Aug-07 9:56
upsb sgdf17-Aug-07 9:56 
Generalhelp! Pin
liloma25-May-06 11:55
liloma25-May-06 11:55 
GeneralRegister more than one HotKeys Pin
dileaa14-Feb-04 1:48
dileaa14-Feb-04 1:48 
GeneralRe: Register more than one HotKeys Pin
Ashley van Gerven16-Feb-04 0:24
Ashley van Gerven16-Feb-04 0:24 
GeneralRe: Register more than one HotKeys Pin
emenell15-May-04 1:53
emenell15-May-04 1:53 
GeneralRe: Register more than one HotKeys Pin
chris91427-Oct-04 15:49
chris91427-Oct-04 15:49 
GeneralRe: Register more than one HotKeys Pin
Soykaf18-Oct-05 1:47
Soykaf18-Oct-05 1:47 
GeneralRe: Register more than one HotKeys Pin
Job V7-May-06 12:32
Job V7-May-06 12:32 
GeneralRe: Register more than one HotKeys Pin
daftvader11-Feb-07 20:35
daftvader11-Feb-07 20:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.