Разрешить глобальные горячие клавиши

Прежде всего, я не настоящий кодер, но я доволен тем, что я сделал до сих пор.

Я написал этот код ниже, который связан с робототехникой. Приведенный ниже код позволяет мне использовать сочетания клавиш при нажатии на форму. Однако мне нужны горячие клавиши, чтобы работать независимо от того, находится ли приложение в фокусе или даже не свернуто.

Я уже смотрел онлайн, но это не очень понятно.

Public Class MainForm

    Private Sub MainForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown

        If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
            DF1Com1.Write("O:1/0", "1")  ' (O:9/0) (R)  
        End If

        'If e.KeyCode = Keys.R Then
        'DF1Com1.Write("O:1/0", "1")  ' (O:9/0) (R)   
        'End If

    End Sub

    Private Sub MainForm_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp

        If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
            DF1Com1.Write("O:1/0", "0")  ' (O:9/0) (R) 
        End If

        'If e.KeyCode = Keys.R Then
        'DF1Com1.Write("O:1/0", "0") ' (O:9/0) (R) 
        'End If

    End Sub

Public Class MainForm


    Private Sub MainForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown

        If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
            DF1Com1.Write("O:1/0", "1")  ' (O:9/0) (R) 
        End If

        'If e.KeyCode = Keys.R Then
        'DF1Com1.Write("O:1/0", "1")  ' (O:9/0) (R)
        'End If

    End Sub

    Private Sub MainForm_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp

        If (e.KeyCode And Not Keys.Modifiers) = Keys.T AndAlso e.Modifiers = Keys.Control Then
            DF1Com1.Write("O:1/0", "0")  ' (O:9/0) (R)  
        End If

        'If e.KeyCode = Keys.R Then
        'DF1Com1.Write("O:1/0", "0") ' (O:9/0) (R) 
        'End If

    End Sub

End Class

Обновить:

Правильно. Я добавил класс, который позволяет GlobalKey быть зарегистрированным.

В моей основной форме у меня теперь есть этот ключ:

   Public Class MainForm
    Dim hkr As New HotKeyRegistryClass(Me.Handle)

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.A).ToString()
        hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.S).ToString()
        hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.D).ToString()
        hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.F).ToString()
        hkr.Register(HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.G).ToString()
        hkr.Register(HotKeyRegistryClass.Modifiers.MOD_SHIFT Or HotKeyRegistryClass.Modifiers.MOD_CTRL, Keys.H).ToString()
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = HotKeyRegistryClass.Messages.WM_HOTKEY Then 'NOT THE ACTUAL WINDOWS NAMESPACE
            Dim ID As String = m.WParam.ToString()
            Select Case ID
                Case 0 : If DF1Com1.Write("O:1/0", "1") Then DF1Com1.Write("O:1/0", "0")
                Case 1 : MessageBox.Show("S")
                Case 2 : MessageBox.Show("D")
                Case 3 : MessageBox.Show("F")
                Case 4 : MessageBox.Show("G")
                Case 5 : MessageBox.Show("H")
            End Select
        End If
        MyBase.WndProc(m)
    End Sub

Если вы посмотрите на случай 0. Это работает, однако это не ставит ключ обратно. Это оставляет это нажатым все время. Мне нужно, когда клавиша нажата, это 'DF1Com1.Write("O:1/0", "0")'

Код класса

Public NotInheritable Class HotKeyRegistryClass
    Private Declare Function RegisterHotKey Lib "user32.dll" (ByVal handle As IntPtr, ByVal id As Int32, ByVal fsModifier As Int32, ByVal vk As Int32) As Int32
    Private Declare Function UnregisterHotKey Lib "user32.dll" (ByVal handle As IntPtr, ByVal id As Int32) As Int32
    Private Handle As IntPtr = IntPtr.Zero
    Private Registry As New System.Collections.Generic.List(Of Int32)
    Public Enum Messages
        [WM_HOTKEY] = &H312
    End Enum
    Public Enum Modifiers
        [MOD_ALT] = &H1
        [MOD_CTRL] = &H2
        [MOD_SHIFT] = &H4
    End Enum
    Sub New(ByVal Handle As IntPtr)
        Me.Handle = Handle
    End Sub
    Public Function Register(ByVal Modifier As Int32, ByVal Key As System.Windows.Forms.Keys) As Int32
        Dim ret As Int32
        ret = NextAvailableIndex()
        Call RegisterHotKey(Me.Handle, ret, Modifier, Key)
        Registry.Insert(ret, ret)
        Return ret
    End Function
    Public Sub Unregister(ByVal ID As Int32)
        Call UnregisterHotKey(Me.Handle, ID)
        Registry.Remove(ID)
    End Sub
    Private Function NextAvailableIndex() As Int32
        Dim ret As Int32 = 0
        Dim n As Int32 = 0
        For i As Int32 = 0 To Registry.Count - 1
            If Registry(i) = n Then
                n = n + 1
            ElseIf n < Registry(i) Then
                Return n
            End If
        Next
        If n = Registry.Count Then
            Return Registry.Count
        End If
        Return ret
    End Function
End Class

2 ответа

Решение

К несчастью, RegisterHotkey только говорит вам, когда комбинация клавиш была активирована. Кроме того, как вы уже поняли, KeyDown а также KeyUp Ваши события будут работать только тогда, когда ваше приложение сфокусировано.

Единственный способ получить действительно глобальный KeyDown а также KeyUp с помощью крючка клавиатуры низкого уровня. Поскольку я не хочу копировать весь свой ответ, я просто сделаю ссылку на него. По этой ссылке вы узнаете, как настроить клавиатуру.

Как отключить / переопределить Windows 10 горячих клавиш с помощью C#

Другая возможность - выполнить обе команды при активации горячей клавиши следующим образом...

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg = HotKeyRegistryClass.Messages.WM_HOTKEY Then 'NOT THE ACTUAL WINDOWS NAMESPACE
            Dim ID As String = m.WParam.ToString()
            Select Case ID
                Case 0 : 
                    DF1Com1.Write("O:1/0", "1")
                    System.Threading.Thread.Sleep(2000)
                    DF1Com1.Write("O:1/0", "0")
                Case 1 : MessageBox.Show("S")
                Case 2 : MessageBox.Show("D")
                Case 3 : MessageBox.Show("F")
                Case 4 : MessageBox.Show("G")
                Case 5 : MessageBox.Show("H")
            End Select
        End If
        MyBase.WndProc(m)
    End Sub

Другим вариантом для достижения этой цели может быть использование логического значения для отслеживания. Делая это, нажмите горячую клавишу, чтобы начать, затем нажмите еще раз, чтобы остановить.

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Static toggle As Boolean
        If m.Msg = HotKeyRegistryClass.Messages.WM_HOTKEY Then 'NOT THE ACTUAL WINDOWS NAMESPACE
            Dim ID As String = m.WParam.ToString()
            Select Case ID
                Case 0 :
            If toggle Then
             DF1Com1.Write("O:1/0", "0")
            Else
                        DF1Com1.Write("O:1/0", "1")
            End If
            toggle = Not toggle
                Case 1 : MessageBox.Show("S")
                Case 2 : MessageBox.Show("D")
                Case 3 : MessageBox.Show("F")
                Case 4 : MessageBox.Show("G")
                Case 5 : MessageBox.Show("H")
            End Select
        End If
        MyBase.WndProc(m)
    End Sub
Другие вопросы по тегам