Introduction

The attached source code is for a system-wide global hotkey control written in Visual Basic 6, originally posted on the Merrion Computing Downloads.

Registering a hotkey

There are two API calls concerned with registering a system wide hotkey: RegisterHotkey and UnregisterHotkey - the declarations are:

To register the hotkey, you need to specify hwnd - the window which will be notified when the hotkey combination is pressed, id - the unique identifier for the hotkey, fsModifiers - the modifiers of the hotkey (i.e. whether ALT, SHIFT, CTRL or WIN keys are pressed) and finally vKey - the virtual key code for the hot key. The modifiers which can be combined together are:

Listening Out for the hotkey

When a hotkey which has been registered successfully is pressed, the window specified in the hwnd is posted a WM_HOTKEY registered window message. Additionally the lParam parameter holds the modifier and virtual key code in its high and low words respectively.

Visual Basic does not handle the WM_HOTKEY message by default which means that you need to subclass the window hwnd in order to respond to it. To do this, you use the API call SetWindowLong with the index GWL_WNDPROC to replace the existing window procedure with yours.

Using the Control in your Application

To use this control in a Visual Basic application, compile the attached source code and then add an instance of the resulting OCX to your project. Add an instance of the MCLHotkey control to your form and press F4 to set the properties. Then add the code that you want executed when the hotkey is pressed to the HotkeyPressed event:

this is great, but i'm kinda dumb, I can't get it working? how do I use it, i read all the documents. never fiddled with the codes. just slopped onto my form.
i tried that [quote]
Private Sub VBHotKey1_HotkeyPressed()
''
End Sub
thing. but I don't know what to do with it, how do I use it with ctrl+1, or ctrl+P and stuff? sorry I'm such a noob. and I'm kinda lost. a litte help here. please. thank you.

I found this control to be very good, however there where a couple of problems that meant I had to edit the original code.

The problems all arise if you wish to use more than one Global Hotkey.

1) If you try and use a second Hotkey it Unregisters the previous.

This is caused because the Atom is a shared variable and it is decremented and then incremented when you register a new Hotkey. This results in each control using the same Atom.

To resolve this I created a new member Variable in SystemWideHotkeyComponent

Private _MyAtom As Int32 = 0

and when I setup the Hotkey the new atom is asigned to this member variable. I also check whether it was previously assigned so only one atom is assigned per control.

from StartHotkeyWatch:

If _MyAtom = 0 Then
mhAtom += 1
_MyAtom = mhAtom
End If

This code ensures that a unique Atom is assigned once per control.

2) The event handlers for each control receive all Hotkey presses.

This is because the event is fired for any Hotkey press and not the individual hotkey relatting to the control. I had to change the Message handler in GlobalHotkeyListener to check whether the correct hotkey had been pressed. Only if the hotkey in LParam matches the listening hotkey does it fire the event.