如何使“KeyDown”和“KeyUp”忽略修饰键以及如何在 Visual Basic 中将键打印到字符串

How to make `KeyDown` and `KeyUp` ignore modifier keys and how to print the key to a string in Visual Basic

在 VB 中,我通常将按键按下时的代码放在 KeyDownKeyUp 子程序中。但是,如果可以将此代码放在 Timer_Tick.

中,我会更喜欢它

所以我在代码中实现了下面显示的方法,程序在启动时创建了一个 List (Of Keys),然后 KeyDownKeyUp subs 添加或删除了 Keys 来自 List.

为了调试,程序在每帧刷新的 Paint 子中绘制所有 Keys 的字符串。

这种处理按键的方法大部分工作正常,除了我遇到的以下问题:

  1. keysPressed(i).ToString 没有像我期望的那样绘制 , 或任何非字母字符。相反,它绘制 Oemcomma。有没有办法来解决这个问题? (我知道现在这并不重要,因为它只是一个调试功能,但我仍然想知道将来如何解决这个问题)

  2. 修改键对我来说很麻烦。按下后,KeyUp sub 一旦释放就不会被调用(我怀疑这是因为他们修改了自己)并且根本没有检测到一些键(比如 fn)。

    此外,如果我按住A,然后按Shift,然后松开A,那么KeyUp for A是'调用(因为它已被修改)这意味着 Keys.A 没有从我的列表中删除。无论是否修改了 A,我都希望 KeyUp 调用 A

    有没有办法告诉 VB 忽略 KeyDownKeyUp 子程序中的所有修改键? (这里我的意思是忽略,因为忽略所有修改,尽管仍然能够检测到修改键被按下)

  3. 当我按下一堆按钮(超过 10 个)时,似乎并没有一次检测到所有按钮(列表中只出现 6 个左右)。有没有办法避免这个错误,或者这是使用 VB?

    的限制

    事实上,偶尔,当我按住另一个按钮的同时再按几个按钮时,我按住的按钮似乎 'cancelled out' 被从列表中删除,直到我松开。 (当我按下很多键时会出现很多错误)。

  4. 当我同时按下多个键时,到底发生了什么? KeyDown 是否为每个键多次调用,或者 KeyDown 实际上可以代表多个键?在这种情况下,我的程序究竟会发生什么?

Public Class Form1
    Dim keysPressed As New List(Of Keys)

    Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown

        If Not keysPressed.Contains(e.KeyData) Then keysPressed.Add(e.KeyData)

        If e.KeyData = Keys.Escape Then End
    End Sub

    Private Sub Form1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp

        keysPressed.Remove(e.KeyData)
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles screenTimer.Tick
        Refresh()
    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint

        For i = 0 To keysPressed.Count - 1
            e.Graphics.DrawString(keysPressed(i).ToString, New System.Drawing.Font("Arial", 10), Brushes.Black, 10 * i, 540)
        Next
    End Sub
End Class
  1. 不行,自己码。对于您的目的而言,它在功能方面和调试方面都很棒,我更喜欢这种方式,所以也许您应该采纳我的建议而不是反对它。考虑查看所有击键的痕迹,然后看到 ,混合了一堆看似合理的键名。想象一下 Ctrl+ 等(在制作这段代码时,您确实需要调试或控制台跟踪每个事件)

  2. 因此,通过删除修饰符来分解键数据。没有办法改变密钥数据到达您的方式。这对某些用途来说很不方便,但对某些用途却很有用。

  3. 是你键盘的问题。通常,您不能一次按下多个键。它与 VB 或 .net

  4. 无关
  5. 正是您所期望的;一次按键只能代表一个键。如果您甚至可以找到一种方法在 KeyEventArgs 中存储有关多个密钥的信息,那么您就是魔术师

尽管不使用 winforms 事件,此处的代码仍会执行您正在尝试的操作:https://github.com/TASVideos/BizHawk/tree/master/BizHawk.Client.EmuHawk/Input;它成串地接收关键事件,但处理它们或多或少与它们来自 winforms 相同。但不管你信不信,我们实际上必须努力重建 winforms 将修饰符与击键相结合的方式(见第 2 点)——不是因为与旧 winforms 代码的兼容性,而是因为这就是我们的方式更喜欢它。