Creating and Responding to Hotkeys
Download the RetHotKey class and basic sample (21kb)
Download the (very foolish) demonstration project (35kb)
Before you Begin
This project requires the SSubTmr.DLL component. Make sure you have loaded and registered this before trying the project.
Win32 allows you to set up combinations of key-presses which can be associated with an
application on a system-wide scope, called Hotkeys. When a user
presses a registered HotKey it doesn't matter which application is active when they
pressed it, the hot-key message will get routed to your application.
There are two types of HotKeys:
This article describes how to create and respond to the second type, Registered HotKeys. If you want to
create a simple activation HotKey, this information is described in the
HotKey Control sample. This also provides an implementation
of the Common Controls HotKey control which you can use in an application to make it easier for
a user to set-up HotKeys.
Application activation HotKeys
These are the simplest type. When the HotKey is selected your application is activated. They
are very simple to set up but they only activate your application - you can't determine if this
was due to the HotKey being pressed nor take any other action.
This type of HotKey sends a WM_HOTKEY message to your application when the HotKey is pressed.
so you can choose how to respond to the key. Setting up this type is slightly more complex
and you have to subclass your application's form to intercept the HotKey messages.
Registering a HotKey
Registering a system-wide HotKey is achieved in two steps:
1. The Win32 Atom Databases
- Creating a globally unique identifier for the HotKey. You do this using the
Win32 Global Atom database.
- Registering the HotKey itself.
Win32 Atom databases store a list of unique strings which are internally identified by an 16 bit integer ID.
The Global Atom database creates string lists which are accessible to all processes. In addition
to this each process on the system can have its own Local Atom database.
These functions could be quite useful for other VB purposes - if you need to store a list of
unique strings and IDs in an application, you could take advantage of the Atom database to do
it. However, as there is only one atom database per process you would have to be careful! Note that
an applications process includes both the executable and any OCXs or DLLs being used in that executable.
The Global Atom database functions in Win32 are GlobalAddAtom, GlobalDeleteAtom, GlobalFindAtom
and GlobalGetAtomName. The first step of registering a HotKey is to create a string that is unlikely
to be in use by any other application on the system and then get an ID for it by calling GlobalAddAtom
for that string. In the class supplied with the demonstration project the string is created by specifying a
local key string to which the executable name and the current GetTickCount value are appended.
2. Registering the HotKey
Registering the key itself is acheived using Win32's unusually sensibly named RegisterHotKey
function. This takes the window handle you want to send the messages to, the globally unique
identifier you created using the Global Atom database, a bit flag containing the Shift, Ctrl,
Alt or Windows Key keys which have to be pressed for the HotKey and the Virtual Key Code of the
key you want to register. Note that in VB the VBRUN library enumeration
KeyCodeConstants corresponds directly to the Win32 Virtual Key Code constants. These
are the key values that are passed to you in the KeyUp and KeyDown events.
Responding to HotKeys
Once you've set up a HotKey, you can respond to it by subclassing the WM_HOTKEY
message sent to the window. The wParam of the WM_HOTKEY message contains the
globally unique identifier you assigned to the HotKey, and the lParam contains the
virtual key code in the HiWord and the key modifiers in the LoWord.
Tip Extract HiWords and LoWords from a Long value
This is easy to do using the And operator and emulating a Right Shift by dividing:
LoWord = (Value And &HFFFF&)
HiWord = (Value \ &H10000) And &HFFFF&
There is a problem with this techique you have to be aware of if the HiWord of the Value
has its highest bit set. In VB, there is no way of defining an Long variable as "Unsigned",
so the high bit of a Long is used to identify whether the number is positive or negative.
If the Value has the high bit set, then the result of the HiWord comparison above will be wrong
(for example, if Value was &HFFFFFFFF, which VB interprets as -1, then the HiWord method above
will yield 0!). To work around this problem, rewrite HiWord like this:
' Check for high bit (sign flag):
If (Value And &H80000000) = &H80000000 Then
' Strip it out whilst shifting then add it back in again afterwards:
HiWord = (((Value And &H7FFFFFFF)\&H10000) Or &H8000) And &HFFFF&
' Standard shift method:
HiWord = (Value \ &H10000) And &HFFFF&
The cRegHotKey class supplied in the download wraps up all of this functionality into a simple
class which you can drop into a project. Using the class you do this:
Private WithEvents m_cHK As cRegHotKey
- Declare a WithEvents instance of the class in your project:
Create an instance of the class and tell it your form's window handle:
Set m_cHK = New cRegHotKey>
Add a HotKey (or as many as you like!):
' This registers CTRL-ALT-C as "MyHotKey"
m_cHK.RegisterKey "MyHotKey", vbKeyC, MOD_CONTROL Or MOD_ALT
Respond to the keypress throught HotKeyPress event
Private Sub m_cHK_HotKeyPress(ByVal sName As String, _
ByVal eModifiers As EHKModifiers, _
ByVal eKey As KeyCodeConstants _
If (sName = "MyHotKey") Then
' Do your processing here!
The alternative download implements a couple of entirely pointless uses of the class. Firstly
CTRL-ALT-C will start and stop a small earthquake on your system. Secondly, CTRL-ALT-X will
attempt to kill with prejustice any instances of the supremely smug Microsoft Assistant thingy
it finds on the screen. On a more useful note, it also demonstrates using the HotKey control
to set up the keys on the screen (this control is included compiled into the source code).
Back to top
Back to Source Code