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

MCL Global Hotkey ActiveX control

By , 12 May 2003
 

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:

Private Sub MCLHotkey1_HotkeyPressed()
  Debug.Print "You pressed the hotkey at " & Now
End Sub
'\\ API Calls used in subclassing windows....
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
	(ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, _
	ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function DefWindowProc Lib "user32" Alias "DefWindowProcA" _
	(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _
	ByVal lParam As Long) As Long
'\\ Window specific information
Private Declare Function GetWindowLongApi Lib "user32" Alias "GetWindowLongA" _
	(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLongApi Lib "user32" Alias "SetWindowLongA" _
	(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Const GWL_WNDPROC = (-4)
Public Function VB_WindowProc(ByVal hwnd As Long, ByVal wMsg As Long, _
	ByVal wParam As Long, ByVal lParam As Long) As Long

Dim VKey As Long
Dim Modifier As Long

If wMsg = WM_HOTKEY Then
    VKey = HiWord(lParam)
    Modifier = LoWord(lParam)
    '\\ Raise an event here to respond to the hotkey
End If

If sWindow.OldWndProc = 0 Then
    VB_WindowProc = DefWindowProc(hwnd, wMsg, wParam, lParam)
Else
    VB_WindowProc = CallWindowProc(sWindow.OldWndProc, hwnd, wMsg, wParam, lParam)
End If

End Function
Public Enum enHotkeyModifiers
    MOD_ALT = &H1
    MOD_CONTROL = &H2
    MOD_SHIFT = &H4
    MOD_WIN = &H8
End Enum
Private Declare Function RegisterHotKey Lib "user32" (ByVal hwnd As Long, _
    ByVal id As Long, ByVal fsModifiers As Long, ByVal vk As Long) As Long
Private Declare Function UnregisterHotKey Lib "user32" (ByVal hwnd As Long, _
    ByVal id As Long) As Long

History

  • 12th May, 2003: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Duncan Edwards Jones
Software Developer (Senior) JP Morgan
Ireland Ireland
Member
C# / SQL Server developer
Microsoft MVP 2006, 2007
Visual Basic .NET

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

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalmisbehave on window vistamemberarunkumar.1658330 Jan '09 - 22:19 
i'm using this code in my project , it work excellent but keys are misbehave in vista
some keys work fine but some are wrong
 
any one can help that it compatible with vista or do i change code
 
thank in advance
Generalthis is great butmemberLeerz5 Dec '06 - 6:16 
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.
 

[/quote]
GeneralRe: this is great butmemberDuncan Edwards Jones8 Feb '07 - 3:51 
You need to set the properties of the component at design time to set which key it responds to e.g.
AltKey = false
Ctrlkey = True
ShiftKey = False
WinKey = false
VKey = vbKey1
 
will fire on CTRL+1
 

 
'--8<------------------------
Ex Datis:
Duncan Jones
Merrion Computing Ltd

GeneralExcellent Control but a couple of problemsmemberAvoSoftwareTeam29 Oct '05 - 2:38 
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.
 
Add this member variable:
Private _KeyMask As Integer
 
Add this to New()
_KeyMask = vkey << 16 Or fsModifiers
 
Finally modify the function bellow:
 
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
Select Case (m.Msg)
Case WM_HOTKEY
If m.LParam.ToInt32 = _KeyMask Then
OnHotkeyPressed(New HotkeyEventArgs(_Key, _Modifier))
End If
End Select
 
Return False
 
End Function
 
Onve you make these changes it all works beautifully.
 
-- modified at 8:40 Saturday 29th October, 2005
GeneralRe: Excellent Control but a couple of problemsmemberDuncan Edwards Jones29 Oct '05 - 6:32 
It looks like this comment was meant for the MCLHotkey .NET control[^] rather than this Vb6 one?
 
I will incorporate your changes in the next release - many thanks.

Sláinte,
Duncan Jones
Merrion Computing Ltd
 
'--8<------------------------
Ex Datis:
Duncan Jones
Merrion Computing Ltd
GeneralDisable the [Ctrl]+[Esc] keyssussAnonymous13 Jan '05 - 11:46 
Hello Sir,
 
How can I use your control to disable the [Ctrl]+[Esc] key combinations
 
Thank You
 
Gary
GeneralGreat but...memberQ_HAL2 Aug '04 - 4:36 
Can I change the properties in runtime-mode?
 
I use MS-Access and the OCX works perfekt, but i don't know
how i can change the properties for the hotkeys in runtime.
 
Can you help me? please? Wink | ;)
GeneralNice Ariticle:reason why I rated this excellentmemberIpog Gates18 Jan '04 - 0:45 

Nice Ariticle:reason why I rated this excellent!

Wink | ;)
 
Encourage everyone
General.NET VersionmemberMerrion13 Jun '03 - 0:45 
There is a dot net version of this control (early beta) at www.merrioncomputing.com/Download/MCLHotkeyNet.zip [^]
 
'--8<------------------------
Ex Datis:
Duncan Jones
Merrion Computing Ltd
GeneralRe: .NET VersionmemberJehosephat22 Nov '04 - 10:34 
Having trouble finding HotkeyPressed event handler in .NET version. Do I implement this? I'm not sure I understand how this part is supposed to work. Forgive my ignorance.
 
-Jeff
GeneralRe: .NET VersionmemberMerrion22 Nov '04 - 12:14 
The .NET version is here...[^]
 
'--8<------------------------
Ex Datis:
Duncan Jones
Merrion Computing Ltd

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 13 May 2003
Article Copyright 2003 by Duncan Edwards Jones
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid