Skip to content

Instantly share code, notes, and snippets.

@audinue
Last active June 6, 2026 11:36
Show Gist options
  • Select an option

  • Save audinue/c96d69ec2934d7340a4a30bb21465dfd to your computer and use it in GitHub Desktop.

Select an option

Save audinue/c96d69ec2934d7340a4a30bb21465dfd to your computer and use it in GitHub Desktop.
Imports System.Windows.Forms
Enum HotkeyModifiers
None = 0
Alt = &H1
Control = &H2
Shift = &H4
Win = &H8
End Enum
Class HotkeyEventArgs
Inherits EventArgs
Private m_Modifier As HotkeyModifiers
Private m_Key As Keys
Public Sub New(ByVal modifier As HotkeyModifiers, ByVal key As Keys)
m_Modifier = modifier
m_Key = key
End Sub
Public ReadOnly Property Modifier() As HotkeyModifiers
Get
Return m_Modifier
End Get
End Property
Public ReadOnly Property Key() As Keys
Get
Return m_Key
End Get
End Property
End Class
Class HotkeyWindow
Inherits NativeWindow
Implements IDisposable
Private Structure RegistrationKey
Public Modifier As HotkeyModifiers
Public Key As Keys
End Structure
Private Const WM_HOTKEY As Integer = &H312
Private m_InternalRegistration As New Dictionary(Of RegistrationKey, Integer)
Private m_ExternalRegistration As New Dictionary(Of Integer, RegistrationKey)
Private m_Counter As Integer
Private Declare Function RegisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer, ByVal fsModifiers As Integer, ByVal vk As Integer) As Boolean
Private Declare Function UnregisterHotKey Lib "user32" (ByVal hWnd As IntPtr, ByVal id As Integer) As Boolean
Protected Overrides Sub WndProc(ByRef m As Message)
MyBase.WndProc(m)
If m.Msg = WM_HOTKEY Then
Dim id As Integer = m.WParam.ToInt32()
If m_ExternalRegistration.ContainsKey(id) Then
Dim registrationKey As RegistrationKey = m_ExternalRegistration(id)
RaiseEvent HotkeyPressed(Me, New HotkeyEventArgs(registrationKey.Modifier, registrationKey.Key))
End If
End If
End Sub
Public Event HotkeyPressed As EventHandler(Of HotkeyEventArgs)
Public Sub New()
CreateHandle(New CreateParams)
End Sub
Public Sub Register(ByVal modifier As HotkeyModifiers, ByVal key As Keys)
Dim registrationKey As New RegistrationKey
registrationKey.Modifier = modifier
registrationKey.Key = key
If m_InternalRegistration.ContainsKey(registrationKey) Then
Exit Sub
End If
m_Counter += 1
If RegisterHotKey(Handle, m_Counter, CInt(modifier), CInt(key)) Then
m_InternalRegistration.Add(registrationKey, m_Counter)
m_ExternalRegistration.Add(m_Counter, registrationKey)
Else
m_Counter -= 1
End If
End Sub
Public Sub Unregister(ByVal modifier As HotkeyModifiers, ByVal key As Keys)
Dim registrationKey As New RegistrationKey
registrationKey.Modifier = modifier
registrationKey.Key = key
If Not m_InternalRegistration.ContainsKey(registrationKey) Then
Exit Sub
End If
Dim id As Integer = m_InternalRegistration(registrationKey)
UnregisterHotKey(Handle, id)
m_InternalRegistration.Remove(registrationKey)
m_ExternalRegistration.Remove(id)
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
For Each registrationKey As RegistrationKey In New List(Of RegistrationKey)(m_InternalRegistration.Keys)
Unregister(registrationKey.Modifier, registrationKey.Key)
Next
DestroyHandle()
End Sub
End Class
Class Hotkey
Private Shared m_Window As HotkeyWindow
Private Shared Sub OnHotkeyPressed(ByVal sender As Object, ByVal e As HotkeyEventArgs)
RaiseEvent HotkeyPressed(sender, e)
End Sub
Private Shared ReadOnly Property Window() As HotkeyWindow
Get
If m_Window Is Nothing Then
m_Window = New HotkeyWindow
AddHandler m_Window.HotkeyPressed, AddressOf OnHotkeyPressed
End If
Return m_Window
End Get
End Property
Shared Event HotkeyPressed As EventHandler(Of HotkeyEventArgs)
Shared Sub Register(ByVal modifier As HotkeyModifiers, ByVal key As Keys)
Window.Register(modifier, key)
End Sub
Shared Sub Unregister(ByVal modifier As HotkeyModifiers, ByVal key As Keys)
Window.Unregister(modifier, key)
End Sub
Shared Sub Dispose()
Window.Dispose()
End Sub
End Class
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment