Option Explicit On

Imports System.Windows.Forms

Public Class Hotkey
    Implements IMessageFilter

    Private _OwnerForm As Form
    Private _HotkeyList As New Dictionary(Of Short, HotKeyObject)
    Private _HotkeyIDList As New Dictionary(Of String, Short)

    ''' <summary>
    ''' Diesem Event wird immer die zugewiesene HotKeyID übergeben, wenn eine HotKey Kombination gedrückt wurde.
    ''' </summary>
    Public Event HotKeyPressed(HotKeyID As String)

    ''' <summary>
    ''' Definiert verfügbare Modfier Keys
    ''' </summary>
    Public Enum ModfierKey As Integer
        MOD_ALT = 1
        MOD_CONTROL = 2
        MOD_SHIFT = 4
        MOD_WIN = 8
    End Enum

    Sub New(pOwnerForm As Form)
        _OwnerForm = pOwnerForm
        Application.AddMessageFilter(Me)
    End Sub

    ''' <summary>
    ''' Diese Funktion fügt einen Hotkey hinzu und registriert ihn auch sofort
    ''' </summary>
    ''' <param name="pKeyCode">Den KeyCode für die Taste</param>
    ''' <param name="pModifiers">Die Zusatztasten wie z.B. Strg oder Alt, diese können auch mit OR kombiniert werden</param>
    ''' <param name="pHotKeyID">Die ID die der Hotkey bekommen soll um diesen zu identifizieren</param>
    Public Sub AddHotKey(pKeyCode As Keys, pModifiers As ModfierKey, pHotKeyID As Integer)
        If _HotkeyIDList.ContainsKey(pHotKeyID) = True Then
            Exit Sub
        End If

        Dim oHotkeyId As Short = NativeMethods.GlobalAddAtom(pHotKeyID.ToString())
        _HotkeyList.Add(oHotkeyId, New HotKeyObject(pKeyCode, pModifiers, pHotKeyID))

        NativeMethods.RegisterHotKey(_OwnerForm.Handle, oHotkeyId, _HotkeyList(oHotkeyId).Modifier, _HotkeyList(oHotkeyId).HotKey)
    End Sub

    ''' <summary>
    ''' Diese Funktion entfernt einen Hotkey und deregistriert ihn auch sofort
    ''' </summary>
    ''' <param name="pHotKeyID">Gibt die HotkeyID an welche entfernt werden soll</param>
    Public Sub RemoveHotKey(ByVal pHotKeyID As Integer)
        If _HotkeyIDList.ContainsKey(pHotKeyID) = False Then
            Exit Sub
        End If

        Dim oHotkeyId As Short = _HotkeyIDList(pHotKeyID)
        _HotkeyIDList.Remove(pHotKeyID)
        _HotkeyList.Remove(oHotkeyId)
        NativeMethods.UnregisterHotKey(_OwnerForm.Handle, CInt(oHotkeyId))
        NativeMethods.GlobalDeleteAtom(oHotkeyId)
    End Sub

    Private Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
        If m.Msg = NativeMethods.WM_HOTKEY Then
            If Clipboard.GetText().Trim() <> String.Empty Then
                RaiseEvent HotKeyPressed(_HotkeyList(CShort(m.WParam)).HotKeyID)
            End If
        End If
        Return False
    End Function

    Public Class HotKeyObject
        Public Property HotKey As Keys
        Public Property Modifier As ModfierKey
        Public Property HotKeyID As Integer
        Public Property AtomID As Short

        Sub New(NewHotKey As Keys, NewModifier As ModfierKey, NewHotKeyID As Integer)
            HotKey = NewHotKey
            Modifier = NewModifier
            HotKeyID = NewHotKeyID
        End Sub
    End Class
End Class
