试图以编程方式按住一个键
Trying to programmatically hold a key down
我正在尝试编写一个应用程序来执行一些基本的流程自动化,方法是将键盘事件(即模拟单键按下和按住)发送到 window 焦点(任何 window,如记事本)。我可以让单键按下工作得很好,但我不能让它按住一个键。即使我执行了一个按键按下事件,然后是长时间的延迟,然后是一个按键……我得到的只是一次按键。
我已经阅读了如此多的教程,并且其中许多都反复阅读了很多遍,以确保我没有遗漏任何内容。然而,每一次,我得到的只是一次按键,它无法按住该键。
以下是我从中找到的代码示例:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/bad5b1f3-cf59-4a2b-889b-257ee590bf99/vb-advanced-key-bot?forum=vbgeneral
我期望发生的是它会发送一个键盘事件,告诉系统按住一个键(例如 aaaaaaaaaaaaaaaaaaa),但我得到的只是一个字符。我曾尝试通过重复按键向系统发送垃圾邮件,但接收应用程序看到按键和按键的不同键盘代码,而不是处于保持状态的按键,因此没有响应,就好像按键实际上被按下了一样。
我做错了什么?他们可能更改了这个 dll 吗?
非常感谢任何能帮助我完成这项工作的人。
Public Class Form1
Private Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Integer, ByVal wMapType As Integer) As Integer
' flag to indicate completion
Dim finished As Boolean = True
' how long to 'press' the Space key
Dim delay As Integer = 3
' how many times to repeat Q and Space
Dim Repeats As Integer
' User closes application during processing
Dim UserInterupt As Boolean = False
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
KeyPreview = True
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
If Not finished Then
TextBox1.AppendText("USER closing" & vbCrLf)
UserInterupt = True
e.Cancel = True
End If
End Sub
Private Sub Form1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress
Select Case e.KeyChar
Case "z", "Z"
e.Handled = True
Repeats = 12
finished = False
Do While Not finished
TextBox1.AppendText("Pressing SPACE" & vbCrLf)
HoldKeyDown(Keys.Space, delay)
Loop
Case "x", "X"
e.Handled = True
TextBox1.AppendText("USER stopping" & vbCrLf)
finished = True
End Select
End Sub
Private Sub HoldKeyDown(ByVal k As Keys, ByVal Hold As Integer)
Dim HoldFor As DateTime = DateTime.Now().AddSeconds(Hold)
keybd_event(k, MapVirtualKey(k, 0), 0, 0)
While HoldFor.Subtract(DateTime.Now()).TotalSeconds > 0
Application.DoEvents()
End While
keybd_event(k, MapVirtualKey(k, 0), 2, 0)
TextBox1.AppendText("SPACE released" & vbCrLf)
Repeats -= 1
If Repeats = 0 Then
finished = True
TextBox1.AppendText("REPEATS completed" & vbCrLf)
End If
If UserInterupt Then End
End Sub
End Class
在进入这个问题的兔子洞后回答我自己的问题。
基本上,唯一的方法就是使用 SendKeys。其他方法都已弃用,因此将不再以这种方式工作。
然而,这不适合您 dead-end。如果您想使用 SendKeys 来“按住”一个键,则以 10 毫秒的间隔向该键发送垃圾邮件,这应该会触发接收应用认为该键已被按下。
我正在尝试编写一个应用程序来执行一些基本的流程自动化,方法是将键盘事件(即模拟单键按下和按住)发送到 window 焦点(任何 window,如记事本)。我可以让单键按下工作得很好,但我不能让它按住一个键。即使我执行了一个按键按下事件,然后是长时间的延迟,然后是一个按键……我得到的只是一次按键。
我已经阅读了如此多的教程,并且其中许多都反复阅读了很多遍,以确保我没有遗漏任何内容。然而,每一次,我得到的只是一次按键,它无法按住该键。
以下是我从中找到的代码示例: https://social.msdn.microsoft.com/Forums/vstudio/en-US/bad5b1f3-cf59-4a2b-889b-257ee590bf99/vb-advanced-key-bot?forum=vbgeneral
我期望发生的是它会发送一个键盘事件,告诉系统按住一个键(例如 aaaaaaaaaaaaaaaaaaa),但我得到的只是一个字符。我曾尝试通过重复按键向系统发送垃圾邮件,但接收应用程序看到按键和按键的不同键盘代码,而不是处于保持状态的按键,因此没有响应,就好像按键实际上被按下了一样。
我做错了什么?他们可能更改了这个 dll 吗?
非常感谢任何能帮助我完成这项工作的人。
Public Class Form1
Private Declare Sub keybd_event Lib "user32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Integer, ByVal dwExtraInfo As Integer)
Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Integer, ByVal wMapType As Integer) As Integer
' flag to indicate completion
Dim finished As Boolean = True
' how long to 'press' the Space key
Dim delay As Integer = 3
' how many times to repeat Q and Space
Dim Repeats As Integer
' User closes application during processing
Dim UserInterupt As Boolean = False
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
KeyPreview = True
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
If Not finished Then
TextBox1.AppendText("USER closing" & vbCrLf)
UserInterupt = True
e.Cancel = True
End If
End Sub
Private Sub Form1_KeyPress(sender As Object, e As KeyPressEventArgs) Handles Me.KeyPress
Select Case e.KeyChar
Case "z", "Z"
e.Handled = True
Repeats = 12
finished = False
Do While Not finished
TextBox1.AppendText("Pressing SPACE" & vbCrLf)
HoldKeyDown(Keys.Space, delay)
Loop
Case "x", "X"
e.Handled = True
TextBox1.AppendText("USER stopping" & vbCrLf)
finished = True
End Select
End Sub
Private Sub HoldKeyDown(ByVal k As Keys, ByVal Hold As Integer)
Dim HoldFor As DateTime = DateTime.Now().AddSeconds(Hold)
keybd_event(k, MapVirtualKey(k, 0), 0, 0)
While HoldFor.Subtract(DateTime.Now()).TotalSeconds > 0
Application.DoEvents()
End While
keybd_event(k, MapVirtualKey(k, 0), 2, 0)
TextBox1.AppendText("SPACE released" & vbCrLf)
Repeats -= 1
If Repeats = 0 Then
finished = True
TextBox1.AppendText("REPEATS completed" & vbCrLf)
End If
If UserInterupt Then End
End Sub
End Class
在进入这个问题的兔子洞后回答我自己的问题。
基本上,唯一的方法就是使用 SendKeys。其他方法都已弃用,因此将不再以这种方式工作。
然而,这不适合您 dead-end。如果您想使用 SendKeys 来“按住”一个键,则以 10 毫秒的间隔向该键发送垃圾邮件,这应该会触发接收应用认为该键已被按下。