我已经开发了一个应用程序(使用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
现在问题是它没有按预期工作。如果选中该复选框,则仅复选框的图像会更改,但不会更改大写锁定状态。仅当我单击两次复选框时,大写锁定状态才会更改。因此,我需要单击两次复选框以切换大写锁定。我怀疑我使用条件语句的方式存在问题。
答案 0 :(得分:1)
问题不在于条件逻辑本身(换句话说,你已经正确地写了If
语句),而是你使用{{1}的方式功能。
考虑键盘上的物理键。当你“按下”某个键时,实际发生了两件事:键掉下来,然后键重新启动。在这两件事之后,一个按键事件被注册为已经发生。
因此,使用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
进行第一次调用,这实际上是“按下”大写锁定键。直到 second 时间,您单击复选框控件,将其重新切换为取消选中,然后进行第二次调用keybd_event
你实际上触发了一个完整的按大写锁定键。
像这样编写代码:
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
即使更好,也请使用SendInput
function而不是弃用的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
函数。除此之外,这允许您检查和处理错误。
请注意,您确实不需要VB.NET中的keybd_event
语法。这是一个旧的VB 6,而不是用VB.NET编写代码的惯用方法。