In a previous post, I showed how a C program can simulate a keystroke in Windows using SendInput. I also posted a subsequent example showing how to simulate a keypress with the Control key included (e.g. Ctrl+V). In this post I’m revisting SendInput, but this time an out-of-focus window is the target for the simulated keystroke(s).
The following C program sends a keypress to a specified window that does not need to be in focus. The keystroke to send is specified as the first command line argument. The second command line argument is a “target” word that appears in the title of the target window. The target word can be anything that appears in the title of the taregt window, but it makes sense to pick something that definitely won’t appear in the title of any other windows. The search word is case sensitive and the simulated keystroke is sent to the first matching window.
// // sendkey.c - Send a key press to a specific window // Written by Ted Burke // Last updated 13-2-2013 // // To compile using gcc: // // gcc -o sendkey.exe sendkey.c // // To send the letter 'a' to a WordPad window: // // sendkey.exe a WordPad // #define WINVER 0x0500 #include <windows.h> #include <stdio.h> int main(int argc, char* argv[]) { // Check number of command line arguments if (argc < 3) { fprintf(stderr, "Too few command line arguments\n"); fprintf(stderr, "Usage: sendkey.exe KEY_TO_SEND"); fprintf(stderr, " WORD_FROM_TARGET_WINDOW_TITLE\n"); return 1; } // Get the character to send from the first command // line argument char char_to_send = toupper(argv[1][0]); // Get first window on desktop HWND firstwindow = FindWindowEx(NULL, NULL, NULL, NULL); HWND window = firstwindow; TCHAR windowtext[MAX_PATH]; // We need to get the console title in case we // accidentally match the search word with it // instead of the intended target window. TCHAR consoletitle[MAX_PATH]; GetConsoleTitle(consoletitle, MAX_PATH); while(1) { fprintf(stderr, "."); // Check window title for a match GetWindowText(window, windowtext, MAX_PATH); if (strstr(windowtext, argv[2]) != NULL && strcmp(windowtext, consoletitle) != 0) break; // Get next window window = FindWindowEx(NULL, window, NULL, NULL); if (window == NULL || window == firstwindow) { fprintf(stderr, "Window not found\n"); return 1; } } fprintf(stderr, "Window found: %s\n", windowtext); // Bring specified window into focus SetForegroundWindow(window); // Create the desired keyboard event INPUT ip; ip.type = INPUT_KEYBOARD; ip.ki.wVk = char_to_send; ip.ki.wScan = 0; ip.ki.dwFlags = 0; ip.ki.time = 0; ip.ki.dwExtraInfo = 0; // Send the keyboard event to the specified window SendInput(1, &ip, sizeof(INPUT)); // Exit normally return 0; }
This is what it looked like in the console where I compiled and ran sendkey.exe:
This screenshot shows the WordPad window that received the ‘A’ key press:
Exactly the code I searched for !
But copying the code to PellesC, it does not compile.
Microsoft extensions are enabled.
Pelles C extensions are enabled.
CCFLAGS : -std:C11 -Tx86-coff -Ot -Ob1 -fp:precise -W1 -Gd -Ze -Zx
#define WINVER 0x0500
#include
#include
POLINK: error: Unresolved external symbol ‘__imp__FindWindowExA@16’.
POLINK: error: Unresolved external symbol ‘__imp__GetWindowTextA@12’.
POLINK: error: Unresolved external symbol ‘__imp__SetForegroundWindow@4’.
POLINK: error: Unresolved external symbol ‘__imp__SendInput@12’.
POLINK: fatal error: 4 unresolved external(s).
Help is appreciated why PellesC does not compile the code.
Hmmm, I don’t know anything about PellesC, I’m afraid, but those errors are from your linker. It looks like it can’t find any Win32 functions. My guess is that you need to add a linker option to your CCFLAGS to explicitly link the Win32 libraries. If I remember rightly, the specific library you want to link is “user32.lib” or something like that. You could try adding “-luser32” to your CCFLAGS list? Or maybe just add user32.lib to your project?
Ted
Ted, it was just to add user32.lib to the project.
Now I added
#pragma comment(lib, “user32.lib”)
to the source code.
Thank’s for looking to my question.
Andre
Great! Glad to hear you got it working.
Ted
Hello, i tried compiling and running your program but i cannot get it to work properly. It will always focus on the cmd window and input the letter there, like this http://puu.sh/9L7aV.png. I tried rewriting the program to ask for input instead of having it as arguments but that made it fail finding a window.
Hmm, that is strange. Could you try running the following command instead, in case the window identification string is case sensitive (not the capital A in Anteckningar):
Please let me know if that makes a difference.
Ted
Hi i already tried that but it gave the same result. But there seemed to be more errors than just that. I started building my own version of the program and i had to set the dwFlag to Unicode to make it type more than 1 character correctly for some reason. But I’ve now successfully made it find a window and print to it. Maybe there was something with the conditions that was throwing it off. Anyway your code was of much help in any case, thank you very much.
This works great, thanks a lot!
As the code above works on unfocused windows as it should, but when the keys are sent the specific window goes into focus.
Would you know of any way to send keys to an unfocused window -without- getting it into focus?
Hi Arie,
No, I’m afraid I don’t know how to do this.
A workaround of sorts which might be adequate is to send the keystroke(s) and let the window come into focus, then use the SetForegroundWindow function to bring back your original window. Here’s the MSDN page for SetForegroundWindow:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms633539%28v=vs.85%29.aspx
Alternatively, you could try using SendMessage or PostMessage as described here:
http://www.rohitab.com/discuss/topic/27529-sending-keystrokes-to-inactive-window/
Ted
Pingback: Quora
What do I do if I want it to press the enter key?
Try changing line 70 to the following:
That’s just substituting the virtual key code for the enter/return key. I can’t test it myself because I’m on Linux here, but hopefully that will do it.
Ted