Imports DD_LIB_Standards
Imports System.Text

Public Class ClassHotkey
    Implements IMessageFilter

    Private Declare Function RegisterHotKey Lib "user32" (
        ByVal Hwnd As IntPtr,
        ByVal ID As Integer,
        ByVal Modifiers As Integer,
        ByVal Key As Integer
    ) As Integer

    Private Declare Function UnregisterHotKey Lib "user32" (
        ByVal Hwnd As IntPtr,
        ByVal ID As Integer
    ) As Integer

    Private Declare Auto Function GetWindowText Lib "user32" (
        ByVal hWnd As IntPtr,
        ByVal lpString As StringBuilder,
        ByVal cch As Integer
    ) As Integer

    Private Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" (ByVal IDString As String) As Short
    Private Declare Function GlobalDeleteAtom Lib "kernel32" (ByVal Atom As Short) As Short
    Private Declare Function GetForegroundWindow Lib "user32" Alias "GetForegroundWindow" () As IntPtr

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

    Private Const WM_HOTKEY As Integer = &H312

    ''' <summary>
    ''' Diesem Event wird immer die zugewiesene HotKeyID übergeben, wenn eine HotKey Kombination gedrückt wurde.
    ''' </summary>
    Public Event HotKeyPressed(ByVal 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(ByVal OwnerForm As Form)
        _OwnerForm = OwnerForm
        Application.AddMessageFilter(Me)
    End Sub

    ''' <summary>
    ''' Diese Funktion fügt einen Hotkey hinzu und registriert ihn auch sofort
    ''' </summary>
    ''' <param name="KeyCode">Den KeyCode für die Taste</param>
    ''' <param name="Modifiers">Die Zusatztasten wie z.B. Strg oder Alt, diese können auch mit OR kombiniert werden</param>
    ''' <param name="HotKeyID">Die ID die der Hotkey bekommen soll um diesen zu identifizieren</param>
    Public Sub AddHotKey(ByVal KeyCode As Keys, ByVal Modifiers As ModfierKey, ByVal HotKeyID As String)
        If _HotkeyIDList.ContainsKey(HotKeyID) = True Then Exit Sub
        Dim ID As Short = GlobalAddAtom(HotKeyID)
        _HotkeyIDList.Add(HotKeyID, ID)
        _HotkeyList.Add(ID, New HotKeyObject(KeyCode, Modifiers, HotKeyID))
        RegisterHotKey(_OwnerForm.Handle, ID, _HotkeyList(ID).Modifier, _HotkeyList(ID).HotKey)
    End Sub

    ''' <summary>
    ''' Diese Funktion entfernt einen Hotkey und deregistriert ihn auch sofort
    ''' </summary>
    ''' <param name="HotKeyID">Gibt die HotkeyID an welche entfernt werden soll</param>
    Public Sub RemoveHotKey(ByVal HotKeyID As String)
        If _HotkeyIDList.ContainsKey(HotKeyID) = False Then Exit Sub
        Dim ID As Short = _HotkeyIDList(HotKeyID)
        _HotkeyIDList.Remove(HotKeyID)
        _HotkeyList.Remove(ID)
        UnregisterHotKey(_OwnerForm.Handle, CInt(ID))
        GlobalDeleteAtom(ID)
    End Sub

    Private Function PreFilterMessage(ByRef m As Message) As Boolean Implements IMessageFilter.PreFilterMessage
        If m.Msg = WM_HOTKEY Then
            If CURRENT_CLIPBOARD_CONTENTS IsNot Nothing Then
                RaiseEvent HotKeyPressed(_HotkeyList(CShort(m.WParam)).HotKeyID)
            End If

        End If
    End Function

    Public Shared Function GetCaption() As String
        Dim oCaption As New StringBuilder(256)
        Dim oWindow As IntPtr = GetForegroundWindow()
        GetWindowText(oWindow, oCaption, oCaption.Capacity)
        CURR_FOCUSED_WINDOWNAME = oCaption.ToString()
        Return oCaption.ToString()
    End Function

    Public Class HotKeyObject
        Public Property HotKey() As Keys
        Public Property Modifier() As ModfierKey
        Public Property HotKeyID() As String
        Public Property AtomID() As Short

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