Creating and Responding to System-Wide Hotkeys
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.
Registering a HotKey
Registering a system-wide HotKey is achieved in two steps:
1. The Win32 Atom Databases
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 do 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 achieved 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 a 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& Else ' Standard shift method: HiWord = (Value \ &H10000) And &HFFFF& End If
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:
The alternative download implements an entirely pointless use of the class: CTRL-ALT-C starts and stops a small earthquake on your system. CTRL-ALT-X used to attempt to kill any instances of the supremely smug Microsoft Assistant thingy it finds on the screen but only works on old versions of Office. More usefully, it also demonstrates using the HotKey control to set up the keys on the screen (this control is included compiled into the source code).