【问题标题】:Issue toggling caps lock with check box in vb .net使用 vb .net 中的复选框发出切换大写锁定
【发布时间】:2016-05-28 22:38:44
【问题描述】:

我开发了一个应用程序(使用 vb .net),可以通过单击复选框来切换大写锁定状态。我已经对程序进行了编码,当我单击复选框时,如果选中它,则必须打开大写锁定,如果未选中,则必须关闭它。以下是代码。

Public Class Form1

Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)

Private Const VK_CAPITAL As Integer = &H14
Private Const VK_SCROLL As Integer = &H91
Private Const VK_NUMLOCK As Integer = &H90

Private Const KEYEVENTF_EXTENDEDKEY As Integer = &H1
Private Const KEYEVENTF_KEYUP As Integer = &H2

Private Sub checkbutton_caps_CheckedChanged(sender As Object, e As EventArgs) Handles checkbutton_caps.CheckStateChanged

    If checkbutton_caps.Checked = True Then
        Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0)
        checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_on.png")

    ElseIf checkbutton_caps.Checked = False Then
        Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
        checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_off.png")

    End If
End Sub
End Class

现在的问题是它没有按预期工作。如果我选中复选框,则只有复选框的图像会更改,而大写锁定状态不会更改。只有当我单击复选框两次时,大写锁定状态才会更改。所以我需要点击复选框两次来切换大写锁定。我怀疑我使用条件语句的方式有问题。

【问题讨论】:

  • ...为什么?你的大写锁定键坏了吗?
  • @CodyGray 不,它没有坏,我只是想创建一个虚拟键盘。
  • 开始 -> 运行 -> osk.exe

标签: vb.net checkbox


【解决方案1】:

问题不在于条件逻辑本身(换句话说,您已经正确编写了If 语句),而在于您使用keybd_event 函数的方式。

想想键盘上的物理键。当你“按下”一个键时,实际上会发生两件事:键下降,然后键恢复。在这两件事发生后,按键事件被注册为已经发生。

因此,使用keybd_event 函数触发按键的正确方法是注入一个按键事件,然后是一个按键事件。所以你实际上需要一对调用:

 Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0)
 Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)

既然您理解了这一点,请回头看看您的代码。复选框控件开始时未选中。第一次单击它时,它会自动检查并触发您的 CheckedChanged 事件处理程序。作为响应,您第一次调用keybd_event,这实际上是“按下”大写锁定键。直到 second 您单击复选框控件,将其 back 切换为未选中状态并将 second 调用到 keybd_event,您实际上触发完全按下大写锁定键。

这样写代码:

Private Sub checkbutton_caps_CheckedChanged(sender As Object, e As EventArgs) Handles checkbutton_caps.CheckStateChanged

    If checkbutton_caps.Checked = True Then
        Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0)
        Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
        checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_on.png")

    ElseIf checkbutton_caps.Checked = False Then
        Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0)
        Call keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
        checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_off.png")

    End If

End Sub

或者,更好的是,将触发按键的逻辑封装在另一个函数中,减少代码重复:

Private Sub SimulateKeyPress(ByVal bVKCode As Byte, ByVal bScanCode As Byte)
     keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0)
     keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
End Sub

Private Sub checkbutton_caps_CheckedChanged(sender As Object, e As EventArgs) Handles checkbutton_caps.CheckStateChanged

    If checkbutton_caps.Checked = True Then
        SimulateKeyPress(VK_CAPITAL, &H45)
        checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_on.png")

    ElseIf checkbutton_caps.Checked = False Then
        SimulateKeyPress(VK_CAPITAL, &H45)
        checkbutton_caps.Image = Image.FromFile("resources\btn_ico_caps_off.png")

    End If

End Sub

甚至更好,使用SendInput function 代替已弃用的keybd_event 函数。除其他外,这使您可以检查和处理错误。

请注意,在 VB.NET 中您确实不需要 Call 语法。那是旧的 VB 6 东西,而不是在 VB.NET 中编写代码的惯用方式。

【讨论】:

  • 感谢您的回答,问题已解决。我从来不知道按键事件是如何运作的,否则我不会犯这个错误。
  • reducing code duplication 如果是这样,为什么不这样:Private Sub checkbutton_caps_CheckedChanged(sender As Object, e As EventArgs) Handles checkbutton_caps.CheckStateChanged keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or 0, 0) keybd_event(VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0) checkbutton_caps.Image = Image.FromFile(CStr(IF(checkbutton_caps.Checked, "resources\btn_ico_caps_on.png","resources\btn_ico_caps_off.png"))) End Sub
  • @Cody Gray 另外需要指出的是,方法,而不是函数 SimulateKeyPress 没有完全使用论点,为什么还要对它们进行分类而不使用它们?甚至不需要那个方法调用来减少代码......也是很好的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-30
  • 2010-10-24
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多