VB Press and hold

I am creating a macro program for recording and playing back mouse and keyboard input. Recording works fine, just like mouse playback, but I am having problems reproducing keyboard input - especially pressing and holding a key for a few seconds before releasing it. This is not equivalent to pressing the key again. This is what I tried:

Technique 1: Me.KeyDown

Private Sub keyboard_pressed() Handles Me.KeyDown Dim keypress = e.KeyData MsgBox(keypress) End Sub 

It works only when the window is in focus.

Technique 2: SendKeys

  Private Sub timer_keyboardplayback_Tick() Handles timer_playback.Tick SendKeys.Send("{LEFT}") timer_playback.Interval = 30 End Sub 

It is not in focus, but repeatedly presses the left arrow, and does not press and hold the arrow

Technique 3: keybd_event

  Public Declare Sub mouse_event Lib "user32" Alias "mouse_event" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long) Private Sub timer_keyboardplayback_Tick() Handles timer_playback.Tick Const keydown = &H1 Const keyup = &H2 Dim VK_LEFT = 37 keybd_event(VK_LEFT, 0, keydown, 0) End Sub 

It is out of focus, but the arrow is not held down

Can someone please show me how I can press and hold the left arrow key for a few seconds and then release it.

+5
source share
1 answer

The keybd_event and mouse_event were deprecated several years ago. Instead, you should use the SendInput() function .

Mimicking input from it from .NET can sometimes be a little complicated, fortunately, although I wrote a library called InputHelper ( Download from GitHub ), which is a wrapper around SendInput() . I set it up so that it covers some of the many different ways of handling input and modeling input, mainly:

  • Simulate keystrokes (internally using SendInput() ).
  • Simulate mouse movement and mouse clicks (also using SendInput() inside).
  • Send virtual keystrokes and mouse clicks to the current / specific window (internally using Window Messages ).
  • Create global, low-level mice and keyboard hooks.

Unfortunately, I did not have time to write the corresponding documentation / wiki about this (except for the XML documentation for each member of the library shown by Visual Studio IntelliSense), but so far you can find little information about creating hooks on the project wiki .

A brief description of what this library consists of:

  • InputHelper.Hooks

    To create global low-level mouse / keyboard hooks (using SetWindowsHookEx() and other related methods). This is partially described in the wiki .

  • InputHelper.Keyboard

    To process / simulate physical keyboard input ( SendInput() and GetAsyncKeyState() ).

  • InputHelper.Mouse

    To process / simulate physical mouse input ( SendInput() ).

  • InputHelper.WindowMessages

    To process / simulate input of a virtual mouse / keyboard, for example, into a specific window ( SendMessage() and PostMessage() ).


Send keystroke

Sending a β€œphysical” keystroke can be performed using two functions:

  • InputHelper.Keyboard.PressKey(Key As Keys, Optional HardwareKey As Boolean)

    Sends two keystrokes (up and down) of the specified key.

    If HardwareKey installed, the function will send the scan code key instead of its Virtual Key Code ( False by default).

  • InputHelper.Keyboard.SetKeyState(Key As Keys, KeyDown As Boolean, Optional HardwareKey As Boolean)

    Sends a single keystroke to the specified key.

    If KeyDown is True , the key will be sent as a KEYDOWN event, otherwise KEYUP.

    HardwareKey is the same as above.

You would use the latter, since you want to control how long you want to hold the key.


Hold down the key for the specified time

To do this, you need to use some kind of timer, as you already did. However, to make things more dynamic, I wrote a function that allows you to specify which key to hold and also how long.

 'Lookup table for the currently held keys. Private HeldKeys As New Dictionary(Of Keys, Tuple(Of Timer, Timer)) ''' <summary> ''' Holds down (and repeats, if specified) the specified key for a certain amount of time. ''' Returns False if the specified key is already being held down. ''' </summary> ''' <param name="Key">The key to hold down.</param> ''' <param name="Time">The amount of time (in milliseconds) to hold the key down for.</param> ''' <param name="RepeatInterval">How often to repeat the key press (in milliseconds, -1 = do not repeat).</param> ''' <remarks></remarks> Public Function HoldKeyFor(ByVal Key As Keys, ByVal Time As Integer, Optional ByVal RepeatInterval As Integer = -1) As Boolean If HeldKeys.ContainsKey(Key) = True Then Return False Dim WaitTimer As New Timer With {.Interval = Time} Dim RepeatTimer As Timer = Nothing If RepeatInterval > 0 Then RepeatTimer = New Timer With {.Interval = RepeatInterval} 'Handler for the repeat timer tick event. AddHandler RepeatTimer.Tick, _ Sub(tsender As Object, te As EventArgs) InputHelper.Keyboard.SetKeyState(Key, True) 'True = Key down. End Sub End If 'Handler for the wait timer tick event. AddHandler WaitTimer.Tick, _ Sub(tsender As Object, te As EventArgs) InputHelper.Keyboard.SetKeyState(Key, False) 'False = Key up. WaitTimer.Stop() WaitTimer.Dispose() If RepeatTimer IsNot Nothing Then RepeatTimer.Stop() RepeatTimer.Dispose() End If HeldKeys.Remove(Key) End Sub 'Add the current key to our lookup table. HeldKeys.Add(Key, New Tuple(Of Timer, Timer)(WaitTimer, RepeatTimer)) WaitTimer.Start() If RepeatTimer IsNot Nothing Then RepeatTimer.Start() 'Initial key press. InputHelper.Keyboard.SetKeyState(Key, True) Return True End Function 

Using an example:

 'Holds down 'A' for 5 seconds, repeating it every 50 milliseconds. HoldKeyFor(Keys.A, 5000, 50) 
+1
source

Source: https://habr.com/ru/post/1274864/


All Articles