Click here to Skip to main content
Click here to Skip to main content

Simple steps to enable Hotkey and ShortcutInput user control

By , 21 Jan 2004
 

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.
    using System.Runtime.InteropServices;
    
  2. Add these static external methods to your form (or a separate class if you prefer).
    [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).
    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.
    // 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:

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.

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:

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:

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:

ShortcutInput1.MinModifiers = 2;

Then check the validity:

bool valid = ShortcutInput1.IsValid;

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

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.

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)

About the Author

Ashley van Gerven
Australia Australia
Member
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.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5membercodertuhin30 Jan '13 - 4:12 
QuestionA bit limited?memberdoctorwho60131 Mar '12 - 10:51 
AnswerRe: A bit limited?memberAshley van Gerven2 Apr '12 - 17:08 
GeneralMy vote of 5memberSecretKingdom6 Feb '12 - 3:18 
QuestionRegistered Hot key ovveride other application hot key.memberksrdhilip7 Dec '11 - 0:32 
QuestionGreat article - thank you!memberjclark239b96 Dec '11 - 15:37 
NewsDisplay HotKey chars [modified]memberxJOx12 Aug '11 - 15:50 
GeneralMy vote of 5memberHanson Cheng18 Mar '11 - 8:25 
QuestionSimple steps to enable HotkeymemberRichardMarx16 Feb '11 - 5:12 
This is for windows application and it dosen't work in WPF, you know.
So could you please provide a WPF C# code for enable and register hotkey like this?
My email address: cloudsupport@hotmail.com
 
Kind Regards,
Richard
GeneralMy vote of 4memberRusselSSC27 Jan '11 - 12:36 
RantThis is not that goodmemberNicolai Schönberg15 Nov '09 - 23:38 
Questionbug?memberaldo hexosa28 Jul '09 - 23:21 
AnswerRe: bug?memberAshley van Gerven29 Jul '09 - 16:36 
GeneralThank youmemberM_B_A13 Jun '09 - 17:29 
Generalmessage still not send to actual activate windowsmembertroiszyzy1 Jul '08 - 2:08 
GeneralThanks for the Register codememberhannahb21 Aug '07 - 6:55 
GeneralCharCodeFromKeys not work for mememberupsb sgdf17 Aug '07 - 9:56 
Generalhelp!memberliloma25 May '06 - 11:55 
GeneralRegister more than one HotKeysmemberdileaa14 Feb '04 - 1:48 
GeneralRe: Register more than one HotKeysmemberAshley van Gerven16 Feb '04 - 0:24 
GeneralRe: Register more than one HotKeysmemberemenell15 May '04 - 1:53 
GeneralRe: Register more than one HotKeysmemberChrisdp91427 Oct '04 - 15:49 
GeneralRe: Register more than one HotKeysmemberSoykaf18 Oct '05 - 1:47 
GeneralRe: Register more than one HotKeysmemberMaxxi867 May '06 - 12:32 
GeneralRe: Register more than one HotKeysmemberdaftvader11 Feb '07 - 20:35 
GeneralRe: Register more than one HotKeysmembersandeep p2 Aug '06 - 20:48 

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 22 Jan 2004
Article Copyright 2004 by Ashley van Gerven
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid