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 
Awesome post.
QuestionA bit limited?memberdoctorwho60131 Mar '12 - 10:51 
I'm a bit confussed.   When the hotkey is pressed how can you determine which hotkey was pressed?   I want 10 hotkeys within a form.   All this does it tell me that "A" hotkey was pressed and to run one and only one method when any of the 10 are...
AnswerRe: A bit limited?memberAshley van Gerven2 Apr '12 - 17:08 
I think you can only have one hotkey per window handle. I'm not sure how to get the precise detail of the hotkey pressed. So for additional functions you could create 'dummy' windows (Form instances). I think the main purpose of the hotkeys is to display a form that is running in the background...
GeneralMy vote of 5memberSecretKingdom6 Feb '12 - 3:18 
Very Helpful! Thank you!
QuestionRegistered Hot key ovveride other application hot key.memberksrdhilip7 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...
QuestionGreat article - thank you!memberjclark239b96 Dec '11 - 15:37 
Worked exactly like you said and was fairly easy to implement.   I would've liked to have seen a couple of other examples on what the hotkey could do besides just show the form, but I ultimately figured out how to put one of my methods there. I'm new to C# so others probably knew right...
NewsDisplay HotKey chars [modified]memberxJOx12 Aug '11 - 15:50 
string hotkey;   private void textBox1_KeyDown(object sender, KeyEventArgs e) { string ctrl = ""; string shift = ""; string alt = "";   if (e.Control) ctrl = "CTRL + ";   if (e.Shift) shift = "SHIFT + ";   if (e.Alt) alt = "ALT...
GeneralMy vote of 5memberHanson Cheng18 Mar '11 - 8:25 
That's exactly what I am looking for. It saves me many time.
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 
good article
RantThis is not that goodmemberNicolai Schönberg15 Nov '09 - 23:38 
Hey,   i dont like the source code style, it is not what i would call "clean" and "meaningfull". you could improve it much.   Nevermind, i found a very clean wrapper for hotkey stuff at http://dotnet-snippets.de/dns/globale-hotkeys-tastenkombinationen-SID356.aspx[^]   It...
Questionbug?memberaldo hexosa28 Jul '09 - 23:21 
it makes hot key in another application does not work. for example my notepad can not copy text when i register a hot key (Ctrl+C) in my application. thanks
AnswerRe: bug?memberAshley van Gerven29 Jul '09 - 16:36 
Hi,   A hot key is not like a shortcut key. A hot key overrides shortcut keys, and is useful when you want to capture key combinations when your application not the active window (e.g. minimized). So the behaviour you're seeing is the expected behaviour. It sounds like you need standard...
GeneralThank youmemberM_B_A13 Jun '09 - 17:29 
Thank you very much for this, after looking on the internet for about 4 hours, I have finally found this, and managed to get it to work.   Thank you   M.Ahrens
Generalmessage still not send to actual activate windowsmembertroiszyzy1 Jul '08 - 2:08 
I have seen , that hotkey work fine. But I still want to send the key press hotkey send to the current activated windows...   How can i do this?   Thanks,
GeneralThanks for the Register codememberhannahb21 Aug '07 - 6:55 
I used the code from example 1 and it worked great. I need a global hotkey to quit my application, and it worked first time.
GeneralCharCodeFromKeys not work for mememberupsb sgdf17 Aug '07 - 9:56 
I try to call it with F7 key and get back zero. then i change the method to this code: return (byte)((int)key & 0xFFFF); i take only the first 4 bits of the key.  
Generalhelp!memberliloma25 May '06 - 11:55 
hi, i got a question for you i hope that you can help me , i'm doing an application for a document managment and you can open a differents files, like excel, word or pdf. we hide the toolbars in excel and word, but do you know how can i block the hotkeys of them? , thanks!! . I hope that you...
GeneralRegister more than one HotKeysmemberdileaa14 Feb '04 - 1:48 
How i can register more than one shortcut, when I use RegisterHotKey more times, I have only last key registred.   Thanks
GeneralRe: Register more than one HotKeysmemberAshley van Gerven16 Feb '04 - 0:24 
Good question... I didn't actually try this. What I can tell you tho is that the second parameter to RegisterHotkey is the indentifier for the hotkey, so using the same value will overwrite the hotkey. For multiple hotkeys you should use different values. The MSDN documentation for the second...
GeneralRe: Register more than one HotKeysmemberemenell15 May '04 - 1:53 
Try this article:   http://www.vbaccelerator.com/home/NET/Code/Libraries/Windows_Messages/Hot_Key_Form/article.asp
GeneralRe: Register more than one HotKeysmemberChrisdp91427 Oct '04 - 15:49 
On the dropdown for the hotkey (letters), how would you get the numpad key availalbe in that ???? Thanks in advanced !
GeneralRe: Register more than one HotKeysmemberSoykaf18 Oct '05 - 1:47 
When I tried to import the article's project into #Develop, I resulted in an application that throws unhandled runtime-errors. It compiles well, but it is not possible to execute it...   Any solution?   Greets - Soykaf
GeneralRe: Register more than one HotKeysmemberMaxxi867 May '06 - 12:32 
Use this:   // Register hotkeys RegisterHotKey(mainScherm.Handle, 1003, 3, (int)'V'); RegisterHotKey(mainScherm.Handle, 49152, 3, (int)'B');   protected override void WndProc(ref Message m) { // If the msg is a hotkey message if...
GeneralRe: Register more than one HotKeysmemberdaftvader11 Feb '07 - 20:35 
Genius, thanks dood. Ive been searching for ages to find a simple way to identify individual keys registered with the RegisterHotkey method.

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