Simulating a keystroke in Win32 (C or C++) using SendInput

This program is a simple example of using the Win32 SendInput function to generate a simulated keystroke. When you run this program, it simply waits 5 seconds and then simulates a press and release of the “A” key on the keyboard.

Here’s the complete source code.

//
// keystroke.c - Pauses, then simulates a key press
// and release of the "A" key.
//
// Written by Ted Burke - last updated 17-4-2012
//
// To compile with MinGW:
//
//		gcc -o keystroke.exe keystroke.c
//
// To run the program:
//
//		keystroke.exe
//
// ...then switch to e.g. a Notepad window and wait
// 5 seconds for the A key to be magically pressed.
//

// Because the SendInput function is only supported in
// Windows 2000 and later, WINVER needs to be set as
// follows so that SendInput gets defined when windows.h
// is included below.
#define WINVER 0x0500
#include <windows.h>

int main()
{
	// This structure will be used to create the keyboard
	// input event.
	INPUT ip;

	// Pause for 5 seconds.
	Sleep(5000);

	// 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 "A" key
	ip.ki.wVk = 0x41; // virtual-key code for the "a" key
	ip.ki.dwFlags = 0; // 0 for key press
	SendInput(1, &ip, sizeof(INPUT));

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

	// Exit normally
	return 0;
}

Here’s a screenshot of the console window where I compiled and ran the program.

As soon as I ran the program in the console window, I switched the focus to a Notepad window where the simulated keystroke typed a character, as shown in the following screenshot.

About these ads
This entry was posted in Uncategorized and tagged , , , , , , . Bookmark the permalink.

46 Responses to Simulating a keystroke in Win32 (C or C++) using SendInput

  1. bram geelen says:

    where can I find the different key codes for different buttons? like 0x41, but for other keys :D

    • batchloaf says:

      Hi Bram,

      Here’s a link to the list of virtual key codes on Microsoft’s MSDN website.

      There is an alternative way of filling the keyboard event structure where you specify the key as a unicode character rather than as a virtual key code. For example, you could simulate pressing the ‘d’ key, with something like the following:

          INPUT ip;
          ip.type = INPUT_KEYBOARD;
          ip.ki.time = 0;
          ip.ki.dwFlags = KEYEVENTF_UNICODE; // Specify the key as a unicode character
          ip.ki.wScan = 'd'; // Which keypress to simulate
          ip.ki.wVk = 0;
          ip.ki.dwExtraInfo = 0;
          SendInput(1, &ip, sizeof(INPUT));
      

      I think you still need to use virtual key codes sometimes though to simulate the special keys on the keyboard, so it’s best to know both ways.

      • bram geelen says:

        thanks for the link!
        However, when I try to compile, I get errors that both INPUT and ip are undeclared.

        D:\eclipse workspace>gcc -o keystroke.exe keystroke.c
        keystroke.c: In function `main':
        keystroke.c:25: `INPUT’ undeclared (first use in this function)
        keystroke.c:25: (Each undeclared identifier is reported only once
        keystroke.c:25: for each function it appears in.)
        keystroke.c:25: parse error before `ip’
        keystroke.c:32: `ip’ undeclared (first use in this function)
        keystroke.c:32: `INPUT_KEYBOARD’ undeclared (first use in this function)

        do I need to compile with a VS compiler?

      • batchloaf says:

        No, you shouldn’t need to use the VC++ compiler. I’m using gcc myself. It’s the version installed with MinGW. Are you using MinGW too?

        Did you definitely include both of the following lines at the start of your program?

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

        The SendInput function (and some related stuff) is defined in a header file that gets included by windows.h. However, the definitions are dependent on the versions of Windows that your compiling for. That’s why the WINVER definition line must come before windows.h is inluded. Basically, it makes sure that windows.h will include all the relevant stuff. If you don’t set WINVER before including windows.h, gcc thinks you want to compile a program that will also be compatible wiith older versions of Windows that didn’t support SendInput etc.

        If that’s not the solution, let me know and I’ll see if I can work out why it’s not working for you.

        Here’s a complete main.c example using the second (unicode) form of SendInput:

        #define WINVER 0x0500
        #include <windows.h>
        
        int main()
        {
        	// Pause for 5 seconds.
        	Sleep(5000);
        
        	// Create input event
        	INPUT ip;
        	ip.type = INPUT_KEYBOARD;
        	ip.ki.time = 0;
        	ip.ki.dwFlags = KEYEVENTF_UNICODE;
        	ip.ki.wScan = 'd';
        	ip.ki.wVk = 0;
        	ip.ki.dwExtraInfo = 0;
        	SendInput(1, &ip, sizeof(INPUT));
        
        	// Exit normally
        	return 0;
        }
        
  2. bram geelen says:

    Thanks! that worked wonderfully!

  3. pyroesp says:

    Hey, thanks for the piece of code. It’s just what I was looking for (hate all that C++ and C# things).
    It’s pretty easy to understand.

    I played with it a bit and I can send a ‘CTRL+V’ command.
    Thanks again for the code !

  4. Cody Baldwin says:

    Wow, exactly what I needed and nice easy to read code. A+ from a fellow C++ programmer!

  5. Pingback: Boot Straight to Desktop in Windows 8 | Black-Pixel

  6. Saravana Kumar p says:

    Can anybody please tell me how to send a key to a window which is not in focus?
    Thanks in advance

  7. Shoxolat says:

    Thanks you for the code. It’s just what I was looking for.

  8. This site was… how do you say it? Relevant!! Finally I’ve found something that
    helped me. Thanks!

  9. Sumit Agrawal says:

    Thank you one of the simplest,Error Less example on net I found

  10. Bob Taylor says:

    Laser sharp. No errors. when compiled as advised.

  11. I was able to use your code to send space bar to games, such as Counter Strike and Icy Tower however I am having a problem with sending the arrows, when trying to simulate the arrows it worked in Notepad and I got it to arrow up and in Counter Strike main menu it kept on arrowing up, while when I tried it in gameplay nothing happened.

    I tried using both Virtual keys and hardware scan codes, but with no luck.

  12. Nadsa says:

    Exactly what I needed… Thanks a lot..

  13. It said that INPUT is not declared in the scope!

  14. batchloaf says:

    Hi Bob,

    I have come across that error before, but never with this version of the code.

    • Have you modified the code in any way, no matter how small and seemingly insignificant?
    • What C compiler are you using? (I used gcc. It should be possible to use another compiler, but maybe some tiny modifications could be required?)
    • What version of Windows are you using?

    The usual reason that people see this particular error is either that the first of the following two lines (lines 23 and 24 of my code above) has been omitted, or that they are both included but in the wrong order:

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

    Line 23 must appear before line 24 because the “windows.h” header file is responsible for providing the definition of the INPUT structure, but it only does so if it knows it’s compiling for versions of Windows later than version 0x0500 (when the INPUT structure was presumably first introduced). Defining WINVER = 0x0500 before including “windows.h” ensures that it includes anything included up to this version of Windows.

    Ted

  15. Can someone help me. I can’t figure out how to send key strokes inside a video game. Is it because they use DirectX? If that is the problem, how do I work around this?

    • batchloaf says:

      Hi Timothy,

      Yes, I think you’re right. Games often receive keyboard input (along with input from game controllers and other intput devices) via DirectX. Specifically, I think it arrives via the DirectInput API. There is also a newer related Microsoft API called Xinput, but I don’t think that handles keyboard.

      I found some information here which suggests you can still use SendInput to simulate keystrokes via DirectInput, but you need to use scan codes for the key. The examples on that page are all in C#, but I tried to adapt my C example above using the information I found there. I’m on a Linux machine here, so I can’t check the following, but I think something like this might work:

      //
      // keystroke.c - Pauses, then simulates a key press
      // and release of the "A" key.
      //
      // Written by Ted Burke - last updated 3-9-2014
      //
      // To compile with MinGW:
      //
      //      gcc -o keystroke.exe keystroke.c
      //
      // To run the program:
      //
      //      keystroke.exe
      //
      // ...then switch to e.g. a Notepad window and wait
      // 5 seconds for the A key to be magically pressed.
      //
       
      // Because the SendInput function is only supported in
      // Windows 2000 and later, WINVER needs to be set as
      // follows so that SendInput gets defined when windows.h
      // is included below.
      
      #define WINVER 0x0500
      #include <windows.h>
       
      int main()
      {
          // This structure will be used to create the keyboard
          // input event.
          INPUT ip;
       
          // Pause for 5 seconds.
          Sleep(5000);
       
          // Set up a generic keyboard event.
          ip.type = INPUT_KEYBOARD;
          ip.ki.wScan = 0x1E; // DirectInput key scancode for the "A" key
          ip.ki.time = 0;
          ip.ki.dwExtraInfo = 0;
       
          // Press the key (using scancode to specify which key)
          ip.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &ip, sizeof(INPUT));
       
          // Release the key (again, using scancode to specify which key)
          ip.ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE;
          SendInput(1, &ip, sizeof(INPUT));
       
          // Exit normally
          return 0;
      }
      

      Note that the DirectInput scancode for the “A” key (the value was 0x1E) came from here:

      http://www.gamespp.com/directx/directInputKeyboardScanCodes.html

      Apparently, these scancode values are defined in the DirectInput header file “dinput.h”, but for simplicity I decided to just paste in the actual value rather than including the header file in case the compiler couldn’t find it. You can find scancodes for other keys (other than the “A” key) at the link above also.

      No guarantees, but give it a try and see what happens! Please let me know how it goes.

      Ted

  16. Thank you so much for the quick response. I am excited to try it out. I am even more excited to compare the latter code to the original.

  17. My first attempt to try the code in Windows was blocked by some errors. I will have fun trying to correct it.

  18. It started working after I placed after #include. Is that the correct thing to insert for something i’m trying to do in Direct X? I will try and find out.

  19. It works everywhere else but not in game.

    • batchloaf says:

      Hmmm, I wonder what the problem is?

      Based on the following pages…

      …it looks like it might be worth trying the modified example below:

      //
      // keystroke.c - Pauses, then simulates a key press
      // and release of the "A" key.
      //
      // Written by Ted Burke - last updated 4-9-2014
      //
      // To compile with MinGW:
      //
      //      gcc -o keystroke.exe keystroke.c
      //
      // To run the program:
      //
      //      keystroke.exe
      //
      // ...then switch to e.g. a Notepad window and wait
      // 5 seconds for the A key to be magically pressed.
      //
       
      // Because the SendInput function is only supported in
      // Windows 2000 and later, WINVER needs to be set as
      // follows so that SendInput gets defined when windows.h
      // is included below.
      
      #define WINVER 0x0500
      #include <windows.h>
       
      int main()
      {
          // This structure will be used to create the keyboard
          // input event.
          INPUT ip;
       
          // Pause for 5 seconds.
          Sleep(5000);
       
          // Set up a keyboard event for the "A" key
          ip.type = INPUT_KEYBOARD;
          ip.ki.wScan = 0x1E; // DirectInput key scancode for the "A" key
          ip.ki.time = 0;
          ip.ki.dwExtraInfo = 0;
       
          // Press the key
          ip.ki.dwFlags = KEYEVENTF_UNICODE;
          SendInput(1, &ip, sizeof(INPUT));
       
          // Release the key
          ip.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
          SendInput(1, &ip, sizeof(INPUT));
       
          // Exit normally
          return 0;
      }
      

      The primary change from my example yesterday is that I’ve switched from using the KEYEVENTF_SCANCODE flag for the keyboard event to using the KEYEVENTF_UNICODE flag. I’m still a little bit confused by the two pieces of documentation I linked above. If this modified example doesn’t work, it could make sense to try changing the wScan value of the keyboard event from this…

      ip.ki.wScan = 0x1E; // DirectInput "A" scancode
      

      …to something like this…

      ip.ki.wScan = 'a'; // ascii value for "a" character
      

      …or this…

      ip.ki.wScan = 'A'; // ascii value for "A" character
      

      To check whether this change of scancode value is working, it should be enough to check in e.g. Notepad. i.e. Getting the right value for wScan is nothing to do with DirectInput – it’s just that a different wScan value may be required when using the KEYEVENTF_UNICODE flag.

      Finally, just make sure that when you’re testing any of these examples with the game that you definitely switch the focus to the game window within five seconds of running the program. In each example above, I have inserted a 5 second delay into the program before the keyboard event is generated, so when you run the program you then have five seconds to switch the focus to whichever window you want to receive the event.

      Ted

      • batchloaf says:

        By the way, I just noticed that WordPress had mangled one line of my code example yesterday.

        Where it said this:

        #include
        

        …of course, it should have said this…

        #include <windows.h>
        

        WordPress has an annoying habit of silently removing anything that’s enclosed in angle brackets because it looks like a HTML tag. Apologies if that caused any confusion!

      • Thank you for the response. I am tempted to test this now, but then I’ll forget to sleep. Is what I should type after #include.

  20. Oh, nvm the last comment. Thank you and Good morning!

  21. Quick question before I really stop trying for the day hehe. Would the above UNICODE example work in notepad?

  22. Oh nvm. You clearly said it should work in notepad.

  23. Thanks for helping me nonstop. I tried and I couldn’t get UNICODE to work in notepad. So I tried SCANCODE with ‘a’ and ‘A’. It works well in notepad but not in the game “MapleStory”(free). I would make sure it prints ‘a’ in notepad then switch over to the game, wait for 10 seconds, then switch back to notepad. It would print in notepad but not in the game. I am thankful that I have learned soooo much more during this journey but it is frustrating to not accomplish the main goal.

  24. I was a bit sad because I thought I was going to succeed with PYAHK. I think deep in my heart I want to do this through C first.

    I found this:

    Hey dude. I can shed some light on this topic. I’ve made several maple scripts now including auto attacks for all warriors and a Kanna map bottling script. The problem you are encountering is that if it’s an auto attack, maple isn’t actually detecting y down per se. When we use our physical keyboard to hold down space for auto attack for example, maple detects a repeated pressed down state that controlsending y down cannot imitate.

    What is the workaround? Assuming that you want to bot an attk, change your y up y down script into a single line of {y 50}. What this will do is send the y key 50 times to maple. Obviously not each press will register because of the speed at which ahk does this, but you can modify 50 into something that lasts approximately how much you want. This is the crude way. A finer way is to look up setkeydelay function and use that to fine tune the sleep between each send of y.

    An example from my kanna script: I found that I could controlsend y down y up style for Vanquisher charm and it worked well. However, for a move like shikigami hunting, it would send the first attack then stop. Thus I changed it to ControlSend,,{y 20}, Maplestory. I apologize this isn’t in formal code format but I’m lazy on my iPad. If you’re still confused, post the name of the skill and how you want to use it. I’ll see how I can help!

    Happy mapling!

    I think I might try something similar in C!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s