允许全局热键

Allowing Global Hotkeys

首先,我不是一个真正的编码员,但我对我迄今为止所做的一切感到满意。

我在下面写了这段与机器人技术有关的代码。下面的代码允许我在您单击表单时使用键盘快捷键。但是,无论应用程序是否处于焦点或什至最小化,我都需要热键来工作。

网上已经看过了,不是很清楚。

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

更新:

没错。我现在添加了一个 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")'

Class代码

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

不幸的是,RegisterHotkey 仅在激活组合键时告诉您。此外,正如您已经意识到的那样,您拥有的 KeyDownKeyUp 事件仅在您的应用获得焦点时才有效。

获得真正全局 KeyDownKeyUp 的唯一方法是使用低级键盘挂钩。因为我不想复制我的整个答案,所以我会简单地 link 到它。 link 将为您提供一些设置键盘挂钩的指导。

另一种可能性是像这样在热键激活时执行两个命令...

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