GetAsyncKeyState重复相同的键

时间:2015-09-12 04:58:21

标签: wpf vb.net

"Pop"
"http://example.com/pop"
"Rock"
"http://example.com/rock"
  1. 问题是如果我这样做,当我按住X约5秒钟 即使我释放X键,它也会无限重复X.
  2. 当我按住X键时,我只想重复X,然后当我释放它时我希望它停止。
  3. 请帮帮我。

    如果我在Keyboard.KeyDown(Keys.X)之后添加Keyboard.KeyUp(Keys.X),那么当我释放密钥时它不会重复它,但是密钥将重复得慢得多而GetAsyncKeyState将需要更长的时间检测按键,这样我就无法做到。 - user1785594 2小时前

    此外,如果我将Timer1间隔增加到50毫秒,那么异步重复问题将变得不那么频繁,但它仍然会这样做,我不认为这是正确的方法。

    Imports InputManager
    'Using inputmanager to send keys
    
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        hotkeyx = GetAsyncKeyState(Keys.X)
                    If hotkeyX < 0 Then
                Keyboard.KeyUp(Keys.X)
                System.Threading.Thread.Sleep(5)
                Keyboard.KeyDown(Keys.X)
                System.Threading.Thread.Sleep(5)
        End If
        'Timer1 interval is 10 ms
    

    &#39; - 谢谢Hans Passant,我制作了一个有效的代码,但我认为我使用了不正确的方法来做到这一点。 由于程序需要keyUP来模拟X键按下,它会有同样的问题,虽然不像以前那样频繁,我不知道如何解决它,所以我只是每10轮增加一次键。有更好的解决方案吗?

1 个答案:

答案 0 :(得分:0)

代码段很奇怪,它会在密钥关闭时生成KeyUp通知。您通常可以依赖GetAsyncKeyState()返回的值来检测键入状态,如果键先前已关闭,则将设置位#0。但是当你有一个Timer滴答声时,这种情况不太可能正常工作,显然你的代码有一个调度程序循环。

因此,您需要跟踪以前的值以检测关键状态:

Private prevState(255) As Boolean

您的计时器Tick事件处理程序现在只需要更新此数组并根据需要生成通知。使其尽可能通用:

Private Sub CheckKey(key As Integer)
    Dim state = GetAsyncKeyState(key)
    If state < 0 Then
        prevState(key) = True
        Keyboard.KeyDown(CType(key, Keys))
    ElseIf prevState(key) Then
        prevState(key) = False
        Keyboard.KeyUp(CType(key, Keys))
    End If
End Sub

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    CheckKey(Keys.X)
End Sub

Declare Function GetAsyncKeyState Lib "user32.dll" (key As Integer) As Short

请注意这样的代码的失败模式。如果按住键很短的时间,小于计时器的间隔,那么你将完全错过它。使用操作系统提供的KeyUp / Down事件要好得多,你永远不会错过。只需使用相同的数组即可生成事件。而且您不能依赖10毫秒定时器间隔,默认值为15.625毫秒。