-1

I need a way to simulate keyboard keys if a certain condition is met, I also need to know if it's the simulated key that's currently pressed or the real key. This needs to work outside the main application.

This is how I would need it to work:

    Dim UserDefinedKey As Keys = Keys.H
    Do
        If GetAsyncKeyState(UserDefinedKey) Then
            Thread.Sleep(30)
            'release the set key
            Thread.Sleep(30)
            'press/hold the set key once, continue the loop if the real key is still been held.
        End If
    Loop While GetAsyncKeyState(UserDefinedKey) '/ loop while real key is being held
    'Real key is no longer held, release the simulated key press.

Any help would be greatly appreciated. (This code is to automate certain things inside of a game which is why it needs to work outside the main application)

I have certain things in place to allow the user to set their own key, this was just a small example of what I need, it's just the keyboard simulating part i'm stuck with and determining if the real key is still pressed or not.

User5152
  • 131
  • 9
  • Hello there! Long time no see! ;) -- Right now you're in luck because another user has asked me to create a keyboard version of my [**`MouseInputHelper`**](https://stackoverflow.com/a/41253296/3740093), which will allow you to spam the same key you're holding without it interfering with `GetAsyncKeyState()`. I'll post an answer when I'm done! – Visual Vincent Jul 18 '17 at 08:09
  • The same code for key strokes is a little more complicated, that's why it is taking a bit of time... – Visual Vincent Jul 18 '17 at 16:49

2 Answers2

1

So sorry for the long wait... Simulating keyboard input via Window Messages turned out to be far much more complicated compared to simulating mouse input in the same way.

Anyway, I am finally done with it so here's a complete InputHelper class for simulating both mouse and keyboard input virtually via the mouse and keyboard input stream or via Window Messages.

Download at GitHub: https://github.com/Visual-Vincent/InputHelper/releases
(source code is too long to be pasted in the answer)

Dim UserDefinedKey As Keys = Keys.H

'Using a regular While-loop is better since you won't need your If-statement then.
While InputHelper.Keyboard.IsKeyDown(UserDefinedKey)
    Dim ActiveWindow As IntPtr = InputHelper.WindowMessages.GetActiveWindow()
    Thread.Sleep(30)
    InputHelper.WindowMessages.SendKey(ActiveWindow, UserDefinedKey, False) 'False = Key up.
    Thread.Sleep(30)
    InputHelper.WindowMessages.SendKey(ActiveWindow, UserDefinedKey, True) 'True = Key down.
End While

A little information about InputHelper's sub-classes:

InputHelper.Keyboard

  • Methods for handling and simulating physical keyboard input (i.e. input detected by GetAsyncKeyState()).

InputHelper.Mouse

  • Methods for handling and simulating physical mouse input.

InputHelper.WindowMessages

  • Methods for handling and simulating virtual keyboard and mouse input (i.e. input that is not detected by GetAsyncKeyState()).

Hope this helps!

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • @Joey : Hmm, that's a problem I've never experienced before... It could be that `WindowMessages.SendKey()` tries to attach itself to the currently active window's thread (in order to find the active child window/control of it), which supposedly resets the state of `GetAsyncKeyState()`. I'll look into it. – Visual Vincent Aug 02 '17 at 06:21
  • @Joey : Also, yes: Any simulation done with `InputHelper.Keyboard` or `InputHelper.Mouse` will interfere with the other keys since they simulate **physical** input (as mentioned in the answer). Anything in `InputHelper.WindowMessages` is what you want to use to simulate fully virtual input that is not detected by `Get(Async)KeyState()`, etc. -- I will make a proper documentation for all the methods in the class when I get the time. – Visual Vincent Aug 02 '17 at 06:24
  • @Joey : How do you notice that they get stuck? I can't seem to reproduce your problem. – Visual Vincent Aug 02 '17 at 20:09
  • @Joey : Made an update. Please download the latest version (same link as in the answer) and try the edited code in my answer. This gets only the active top-level window (since games usually do not have child windows) and will hopefully fix your problem as it doesn't mess with other threads and thus not the current keyboard state. – Visual Vincent Aug 03 '17 at 20:19
  • @Joey : No problem, glad I could help! Good luck with your project! – Visual Vincent Aug 04 '17 at 08:28
  • @Joey : Don't worry, you're not bothering. I'm glad to help you out ;). -- Wow, what you experience is really odd behaviour. Can you run the app via Visual Studio and add `Console.WriteLine(ActiveWindow)` in the loop, then hold the key for a while until it stops working... When you've released the key check the [**Output Window**](https://msdn.microsoft.com/en-us/library/3hk6fby3.aspx) in VS and see if it's written the same number every time. – Visual Vincent Aug 07 '17 at 09:09
  • @Joey : If it writes the same number all the time then it's either failing to send the key messages, or the game/app you're sending them to stops handling them. I will try the code on one of my games and see if I get the same problem. – Visual Vincent Aug 07 '17 at 09:10
  • @Joey : Nope. If anything, a fullscreen game would cause troubles. Windowed mode is good ;). -- I have tested it out and I don't experience the problem you described. For me it keeps pressing `H` without a problem. – Visual Vincent Aug 07 '17 at 21:55
  • @Joey : As a workaround you could make it press a button (that doesn't have an in-game function) every now and then (if pressing another button stops it from being stuck). -- What kind of game is it? Perhaps it has some kind of key spam protection? – Visual Vincent Aug 07 '17 at 21:56
  • @Joey : It _could_ be that the game expects the key to go up after a certain amount of time (that is less than approximately 30 ms). Don't know, just suggesting ;). -- Glad you found a solution, good luck! – Visual Vincent Aug 07 '17 at 23:02
0

You will need Windows API hooks for that (nothing for beginners), or third party library like MouseKeyHook

Ondřej
  • 1,645
  • 1
  • 18
  • 29
  • He's looking to _press_ the same key that he is holding, not _detect_ a key stroke. He already detects key strokes via `GetAsyncKeyState()`. -- The problem is that the standard ways of detecting key strokes (`GetAsyncKeyState()`, hooks. etc.) also detect _virtual_ keys, which causes his code to run indefinitely. – Visual Vincent Jul 18 '17 at 16:44