HotkeyManager
Meh, was bored tonight so I whipped up a class to manage your hotkeys.
Straight up, here's the raw source, I'll do some explaining in a sec:
Okay, that class encapsulates everything you need for a basic hotkey trigger. Basically the class is a singleton (i.e you can't instantiate it a dickload of times and clog the message queue), which sets a system-wide, low-level hook which monitors the keypresses of the system. You don't really need to know the inner workings of the class but the code's there if you wanna study it and figure out what it does, pretty simple shit.
The main thing you need to know is how to use it.
Because this is a static (shared) class, you don't need to construct it. However, you do need to initialize it at some point to originally set the hook.
And that's it, your HotkeyManager is now active until you call
The next thing you need to know is how to add a new hotkey to the manager. This is fairly simple, all you need is a callback method.
A quick explanation: A callback is a function that is invoked by the HotkeyManager when your hotkey is pressed. The callback method signature must match the following
For example:
Is a valid method signature for your callback. The "params" argument is an array of objects that you elect to be passed to your callback when the hotkey is pressed. This is the most generic way I could devise the callback to operate so you can fill in as many parameters as you want of any type.
Okay, now you have a callback function in place, so when the user presses a given key (in my case, "E"), the function "E_KeyPressed" will be called. All that's left to do is register the hotkey with the HotkeyManager
Now, here's a very basic "E_KeyPressed" function:
Which will basically just print each parameter to the Output window to make sure everything was passed correctly. How you implement your callback is up to you. You don't have to specify any parameters if you aren't going to use them, just put "Nothing" as the argument in RegisterHotkey.
If you have any questions, feel free to ask.
EDIT: New vid.
Straight up, here's the raw source, I'll do some explaining in a sec:
Code:
Imports System.Runtime.InteropServices
Public NotInheritable Class HotkeyManager
'**************** [Delegates] **************
Public Delegate Sub HotkeyCallback(ByVal pParams As Object())
Private Delegate Function HookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
'************** [End Delegates] ************
Private Const WH_KEYBOARD_LL As Integer = &HD 'constant for a low-level keyboard hook.
'********* [Windows API Functions] *********
<DllImport("user32.dll", CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal pHook As HookProc, ByVal hMod As IntPtr, ByVal dwThreadId As UInteger) As IntPtr
End Function
<DllImport("user32.dll", CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function UnhookWindowsHookEx(ByVal hHook As IntPtr) As Integer
End Function
<DllImport("user32.dll", CallingConvention:=CallingConvention.Winapi)> _
Private Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
End Function
'******* [End Windows API Functions] *******
'*********** [Instance Variables] **********
Private Shared __hhook As IntPtr
Private Shared __hotkeys As Dictionary(Of Integer, Hotkey)
Private Shared __ishk As Boolean
Public Shared Property IsHooked() As Boolean
Get
Return HotkeyManager.__ishk
End Get
Private Set(ByVal value As Boolean)
HotkeyManager.__ishk = value
End Set
End Property
'********* [End Instance Variables] ********
' Initialize the hook if it isn't already. This has to be called before the hook will work.
Public Shared Sub Initialize()
If Not HotkeyManager.IsHooked Then 'check if the hook has already been initialized.
Dim pBaseModule As ProcessModule = Process.GetCurrentProcess().MainModule
Dim pBaseAddress As IntPtr = CType(If(pBaseModule IsNot Nothing, pBaseModule.BaseAddress, New IntPtr(0)), IntPtr)
HotkeyManager.__hhook = SetWindowsHookEx(WH_KEYBOARD_LL, New HookProc(AddressOf KeyboardCallback), pBaseAddress, 0)'attempt to set the hook.
HotkeyManager.IsHooked = (HotkeyManager.__hhook <> IntPtr.Zero)
If HotkeyManager.__hotkeys Is Nothing Then
'if need be, initialize the dictionary for use.
HotkeyManager.__hotkeys = New Dictionary(Of Integer, Hotkey)()
End If
End If
End Sub
'turn the manager off, to turn it back on just call Initialize again.
Public Shared Sub Disable()
HotkeyManager.IsHooked = (UnhookWindowsHookEx(HotkeyManager.__hhook) <> 0)
End Sub
'Unset the hook and reset the key list.
Public Shared Sub Destroy()
HotkeyManager.__hotkeys = Nothing
HotkeyManager.IsHooked = (UnhookWindowsHookEx(HotkeyManager.__hhook) <> 0)
End Sub
'internal callback method. Will trigger a hotkey event only when the key is pressed down.
Private Shared Function KeyboardCallback(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
Dim l_param As Integer = Marshal.ReadInt32(lParam) 'read the keycode.
If wParam.ToInt32() = &H100 AndAlso HotkeyManager.__hotkeys.ContainsKey(l_param) Then 'check if this is a keydown, and if the hotkey is internally registered.
Dim hCallback As HotkeyCallback = HotkeyManager.__hotkeys(l_param).Callback
hCallback(HotkeyManager.__hotkeys(l_param).Paramet ers)
End If
Return CallNextHookEx(HotkeyManager.__hhook, nCode, wParam, lParam)
End Function
'register a hotkey if it doesn't already exist with a provided callback.
Public Shared Sub RegisterHotkey(ByVal key As Integer, ByVal hkproc As HotkeyCallback, ByVal oParams As Object())
If Not HotkeyManager.__hotkeys.ContainsKey(key) AndAlso hkproc IsNot Nothing Then
HotkeyManager.__hotkeys.Add(key, New Hotkey() With {.Callback = hkproc, .Parameters = oParams})
End If
End Sub
'Clear an existing hotkey if it exists.
Public Shared Sub UnregisterHotkey(ByVal key As Integer)
If HotkeyManager.__hotkeys.ContainsKey(key) Then
HotkeyManager.__hotkeys.Remove(key)
End If
End Sub
Private Structure Hotkey
Public Callback As HotkeyCallback
Public Parameters As Object()
End Structure
End Class
The main thing you need to know is how to use it.
Because this is a static (shared) class, you don't need to construct it. However, you do need to initialize it at some point to originally set the hook.
Code:
HotkeyManager.Initialize()
Code:
HotkeyManager.Destroy() 'this will clear all your registered hotkeys as well as turn off the manager. 'or HotkeyManager.Disable() 'this will just turn the hotkey manager off, but still retain all your registered hotkeys for the next time you call Initialize()
A quick explanation: A callback is a function that is invoked by the HotkeyManager when your hotkey is pressed. The callback method signature must match the following
Code:
<access modifier> Sub <function name>(ByVal <parameter name> As Object()) End Sub
Code:
Private Sub E_KeyPressed(ByVal params As Object()) End Sub
Okay, now you have a callback function in place, so when the user presses a given key (in my case, "E"), the function "E_KeyPressed" will be called. All that's left to do is register the hotkey with the HotkeyManager
Code:
HotkeyManager.Initialize()
Dim my_key As Integer = CType(Keys.E, Integer) 'I will be using the "E" key as my hotkey.
Dim my_callback As HotkeyManager.HotkeyCallback = new HotkeyManager.HotkeyCallback(AddressOf E_KeyPressed) 'create a new Callback delegate.
Dim my_parameters As String() = {"this", "is", "an", "example"} 'these will be the parameters I pass to E_KeyPressed whenever it's called
HotkeyManager.RegisterHotkey(my_key, my_callback, my_parameters) 'now the hotkey is registered. Press 'E' and the function will be called.
Code:
Private Sub E_KeyPressed(ByVal params As Object())
For Each o As Object in params
Debug.WriteLine(o.ToString())
Next o
End Sub
If you have any questions, feel free to ask.
EDIT: New vid.