首页 > 解决方案 > VB.NET 如何在将其捕获为热键时避免第一次按键?

问题描述

我设法让我的应用程序捕获任何键以将其用作热键,但是当我按下该键时,热键功能被激活。这是我到目前为止所拥有的:

Private Sub tmrFunc_Tick(sender As Object, e As EventArgs) Handles tmrFunc.Tick
  'Function
End Sub

Private Sub tmrKey_Tick(sender As Object, e As EventArgs) Handles tmrKey.Tick
  'Uses the hotkey to start and stop tmrF
End Sub

Private Sub lblCapKey_Click(sender As Object, e As EventArgs) Handles lblCapKey.Click
    tmrKey.Enabled = False
    txtbStartFunc.Enabled = True
    txtbStartFunc.Text = "Press any key"
    txtbStartFunc.Focus()
End Sub

Private Sub txtbStartFunc_KeyDown(sender As Object, e As KeyEventArgs) Handles txtbStartFunc.KeyDown
    If e.KeyCode = Keys.F10 Then
        txtbStartFunc.Text = "F10"
    End If
    tmrKey.Enabled = True
    txtbStartFunc.Enabled = False
End Sub

当前代码完美地捕获了该键并将其用作热键,问题是热键在第一次按下时激活,导致它在错误的时间意外激活。

我目前的目标是该功能不是通过第一次按键激活,而是通过以下按键激活。

我期待这样的事情:

Private Sub txtbStartFunc_KeyDown(sender As Object, e As KeyEventArgs) Handles txtbStartFunc.KeyDown
    If e.KeyCode = Keys.F10 Then
        txtbStartFunc.Text = "F10"
    End If
    tmrKey.Enabled = True
    '=========================
    tmrFunc.Enabled = False
    '=========================
    txtbStartFunc.Enabled = False
End Sub

标签: vb.net

解决方案


这是一个最终对我有用的解决方案。它允许您在 F1 和 F10 之间设置热键,但不会让您为它们选择相同的键。

在此处输入图像描述

这与您所拥有的完全不同,因此请花点时间研究它并根据需要提出尽可能多的问题:

Public Class Form1

    Private Const KeyDownBit As Integer = &H8000

    Private Enum HotKeyType
        StartClicker
        StopClicker
    End Enum

    Private _StartHotkey As Keys
    Private _StopHotKey As Keys
    Private SelectingHotKey As HotKeyType
    Private HotKeySelected As Boolean = False
    Private _SettingHotKey As Boolean = False
    Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKeys As Integer) As Short

    Private Property StartHotKey As Keys
        Get
            Return _StartHotkey
        End Get
        Set(value As Keys)
            If value <> StopHotKey Then
                _StartHotkey = value
                TextBox1.Text = StartHotKey.ToString
            End If
        End Set
    End Property

    Private Property StopHotKey As Keys
        Get
            Return _StopHotKey
        End Get
        Set(value As Keys)
            If value <> StartHotKey Then
                _StopHotKey = value
                TextBox2.Text = StopHotKey.ToString
            End If
        End Set
    End Property

    Private Property SettingHotKey As Boolean
        Get
            Return _SettingHotKey
        End Get
        Set(value As Boolean)
            If value Then
                HotKeySelected = False
                Timer2.Stop()
            Else
                Timer2.Start()
            End If
            _SettingHotKey = value
        End Set
    End Property

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.KeyPreview = True
        Timer1.Enabled = False
        Timer2.Enabled = False
        Timer1.Interval = 50
        Timer2.Interval = 50

        TextBox1.ReadOnly = True ' they just stay this way all the time
        TextBox2.ReadOnly = True ' they just stay this way all the time

        StartHotKey = Keys.F1
        StopHotKey = Keys.F2
        Timer2.Start()
    End Sub

    Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
        Dim startKeyDown, stopKeyDown As Boolean

        GetAsyncKeyState(StartHotKey) ' disregard first call to "flush it"
        startKeyDown = (GetAsyncKeyState(StartHotKey) And KeyDownBit) = KeyDownBit ' see if it's down
        GetAsyncKeyState(StopHotKey) ' disregard first call to "flush it"
        stopKeyDown = (GetAsyncKeyState(StopHotKey) And KeyDownBit) = KeyDownBit ' see if it's down

        TextBox1.BackColor = If(startKeyDown, Color.Green, Control.DefaultBackColor)
        TextBox2.BackColor = If(stopKeyDown, Color.Green, Control.DefaultBackColor)

        If startKeyDown Then
            Timer1.Start()
        End If
        If stopKeyDown Then ' if you hold both down, then it'll stop
            Timer1.Stop()
            Label1.BackColor = Control.DefaultBackColor
        End If
    End Sub

    Private Sub BothButtons_Click(sender As Object, e As EventArgs) Handles Button1.Click, Button2.Click
        SelectingHotKey = If(sender Is Button1, HotKeyType.StartClicker, HotKeyType.StopClicker)
        SettingHotKey = True ' automatically turns off Timer2
        Dim tb As TextBox = If(sender Is Button1, TextBox1, TextBox2)
        tb.Text = "Press F1 to F10"
    End Sub

    Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
        Select Case keyData
            Case Keys.F1 To Keys.F10
                If SettingHotKey Then
                    If SelectingHotKey = HotKeyType.StartClicker Then
                        If keyData <> StopHotKey Then
                            StartHotKey = keyData
                            HotKeySelected = True
                            Return True
                        End If
                    Else
                        If keyData <> StartHotKey Then
                            StopHotKey = keyData
                            HotKeySelected = True
                            Return True
                        End If
                    End If
                End If
        End Select
        Return MyBase.ProcessCmdKey(msg, keyData)
    End Function

    Private Sub Form1_KeyUp(sender As Object, e As KeyEventArgs) Handles Me.KeyUp
        If SettingHotKey AndAlso HotKeySelected Then
            SettingHotKey = False ' restarts Timer2 once selected key has been released
        End If
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        Label1.BackColor = Color.Green
        Label1.Text = DateTime.Now.ToString("HH:mm:ss.ffff") ' just to show it's "clicking"
    End Sub

End Class

推荐阅读