11

I wanted to write a c++ code to emulate pressing a keyboard key "A":

// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;

// Press the "..." key
ip.ki.wVk = code; // virtual-key code for the "a" key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

// Release the "..." key
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
SendInput(1, &ip, sizeof(INPUT));

It works fine when I launch other program and wait to my program execute, the "A" is clicked and first program react to it. But I found that in the other application my action was somehow prevented (I can manually press "A" on keyboard, but using my program do not cause any action).

So, what I can do to make pressing "A" from program more identical to manually pressed "A" (so the second program won't recognize that it was called from program)?

I do not have source code of second program and do not know how it recognize that "A" wasn't pressed manually.

I'm sure that the window I want to react to my code is foreground, receive and block my key (so it can decide that event doesn't come from user but from program).

IInspectable
  • 46,945
  • 8
  • 85
  • 181
PolGraphic
  • 3,233
  • 11
  • 51
  • 108
  • 1
    `SendInput` was invented to resolve the issues with sending individual keyboard messages in individual calls to `keybd_event`. Don't abuse `SendInput` by invoking it several times with a single `INPUT` structure. Build an array of `INPUT` structures and send them in one go. – IInspectable Sep 05 '13 at 22:53
  • I also used keybd_event with the same result. Still thx for pointing some tips. – PolGraphic Sep 05 '13 at 23:35
  • I doubt this question will go anywhere until you give more details about this "second program". – Hans Passant Sep 05 '13 at 23:44
  • There is a [few](http://blogs.msdn.com/b/oldnewthing/archive/2010/12/21/10107494.aspx) [related](http://blogs.msdn.com/b/oldnewthing/archive/2012/11/01/10364713.aspx) posts at the OldNewThing that might be of interest... – Bhargav Sep 06 '13 at 03:16
  • afaik. it seems that the other program always check the hwnd of the sender. it is a kind of protection. – Maher Sep 18 '13 at 20:20

3 Answers3

26

You can use SendInput() to send hardware scan codes as well (as opposed to virtual scan codes, which DirectInput might ignore). It's poorly documented, but SendInput() can indeed bypass DirectInput. The reason Eric's solution didn't work is he set the hardware scan code, but ended up using a virtual scan code (by setting dwFlags to 0 and wVk to non-zero).

Essentially, to do a key press you want to set:

ip.ki.dwFlags = KEYEVENTF_SCANCODE;

And to do a key release, set:

ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;

A full working sample is below and it prints the letter 'a'. You can find other scan codes here.

#define WINVER 0x0500
#include <windows.h>

using namespace std;

int main()
{

    //Structure for the keyboard event
    INPUT ip;

    Sleep(5000);

    //Set up the INPUT structure
    ip.type = INPUT_KEYBOARD;
    ip.ki.time = 0;
    ip.ki.wVk = 0; //We're doing scan codes instead
    ip.ki.dwExtraInfo = 0;

    //This let's you do a hardware scan instead of a virtual keypress
    ip.ki.dwFlags = KEYEVENTF_SCANCODE;
    ip.ki.wScan = 0x1E;  //Set a unicode character to use (A)

    //Send the press
    SendInput(1, &ip, sizeof(INPUT));

    //Prepare a keyup event
    ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));



    return 0;
}

Note: You can combine keypresses (like, shift + a for A) by passing SendInput() an array of INPUT structures.

David
  • 553
  • 1
  • 5
  • 12
  • 1
    Is it also possible to simulate a mouse click that way? – Dave Chandler Jul 10 '14 at 09:50
  • Yup. Use ip.type = INPUT_MOUSE. – David Jul 14 '14 at 18:37
  • Ok. But what do I need to pass as a wScan parameter? Is there a Unicode character representing a mouse click? – Dave Chandler Jul 15 '14 at 08:54
  • Not quite. The INPUT structure is a union, and .ki is what's used for keyboard input. Instead, you'd want to use the .mi field, which is a structure that takes in the mouse position, the mouse event (scroll wheel, left click, etc.), and the duration. Check out [this msdn page](http://msdn.microsoft.com/en-us/library/windows/desktop/ms646273(v=vs.85).aspx) – David Jul 15 '14 at 20:28
  • 2
    Even though I know better, I searched for unicode characters instead of scan codes for the key I need. Hopefully this link saves someone else from temporary idiocy: http://www.philipstorr.id.au/pcbook/book3/scancode.htm – JR Smith Jun 03 '15 at 01:11
  • I'm using the same method. But i'm not able to send input to a specific process only. So the app is keeping the entire computer busy while operational. Since they are being blocked by the games, I can't use the SendMessage or PostMessage methods eighter. It would be a great bonus to send input to a specific process in background & being able to use the computer while doing so. – Evren Ozturk Jun 02 '20 at 10:45
  • You can use the Win32 `MapVirtualKey/Ex()` API to get a scan code for a virtual key code, and vice versa. – Remy Lebeau Dec 19 '22 at 20:16
5

You often need to set the scan code:

// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = MapVirtualKey(code, MAPVK_VK_TO_VSC); // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;

// Press the "..." key
ip.ki.wVk = code; // virtual-key code for the "a" key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

And building an array as IInspectable suggests is also definitely the way to go.

Eric Brown
  • 13,774
  • 7
  • 30
  • 71
  • Thanks for a tip. Unfortunately it doesn't works either. I want to write game bot, still only in chat window my program works (it can put characters in the chat window after I activate that window by clicking on it), but in the game (chat off) the keys stop working (I believe that it is some kind of filter that decide that input comes from program not user). – PolGraphic Sep 10 '13 at 00:30
  • @PolGraphic The game might be using DirectInput to retrieve keyboard input. DirectInput talks directly to the driver, which makes injection rather problematic. Does the game distinguish between lower-case A and capital A? – Eric Brown Sep 10 '13 at 07:18
  • When I use it for moving chacarter with WSAD (I cannot do it from code, only manual pressing keys on keyboard works), it make not difference between lower-case and capital, in game chat window (which I can affect with my code), it makes a difference. – PolGraphic Sep 12 '13 at 17:31
  • That implies that the game may well be using DirectInput. Injection *might* still be possible, but is much harder; you need to open the raw keyboard device and send some IOCTLs to inject raw scan codes. I'm not that familiar with these APIs, so you're on your own... – Eric Brown Sep 12 '13 at 18:10
1

If you are looking to create a game bot, have you looked at the program AutoHotKey? http://www.autohotkey.com/

It offers a scripting language, that allows you to do a lot of the tasks involved in 'bot' creation and it's rather easier than trying to do it all in C++

(It certainly played Farmville for me, when all my family pressured me into creating an account)

Strings
  • 1,674
  • 10
  • 16
  • and you might want to look at this, if the game is 3D - http://www.autohotkey.com/board/topic/63664-solved-imagesearch-failure-wdirectx-fullscreen-gamewin7/ – Strings Sep 19 '13 at 14:13
  • Those apps are awesome of course. But most of them are being recognized by the games & causing the game to shutdown or worse get you banned. so I prefer to write my own apps, they never get recognized. – Evren Ozturk Jun 02 '20 at 10:37
  • 1
    It is very easy for games (or any app) to differentiate between "fake" app-generated input and "real" hardware input. Try all you want, but if they don't want to accept simulated input then they wont accept simulated input, period. – Remy Lebeau Dec 19 '22 at 20:14