Breaking down a string and using keybd to send characters - c++

I have searched the internet for a good system for emulating keypresses in C++.
I want to send a string to another program but as far as I can see the GenerateKey function can only send one at a time. I created code to break a string down and send each letter individually but sometimes the number of a specific letter in the alphabet is sent instead of the letter itself. (e.g. I enter "h" the computer spits out "8")
How can I fix this and is there a better way to do it? Thank you!
#include <windows.h>
#include<iostream>
#include <winable.h>
#include <fstream>
#include<time.h>
#include<string>
using namespace std;
void GenerateKey(int vk, BOOL bExtended) {
KEYBDINPUT kb = {0};
INPUT Input = {0};
/* Generate a "key down" */
if (bExtended) { kb.dwFlags = KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
/* Generate a "key up" */
ZeroMemory(&kb, sizeof(KEYBDINPUT));
ZeroMemory(&Input, sizeof(INPUT));
kb.dwFlags = KEYEVENTF_KEYUP;
if (bExtended) { kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
return;
}
int main() {
SetConsoleTitle( "sendkeys" );
string sentence;
while (1){
cin>>sentence;
char letter;
int track = 0;
while(sentence[track] != '\0') {
cout<<sentence[track];
letter = sentence[track];
GenerateKey(letter, FALSE);
track++;
}
}
}

This sort of approach is really complicated (you have to manage state of SHIFT, CONTROL, and ALT, convert special characters to ALT+0xyz combos) and if the user changes keyboard focus in the process, keys can go to the wrong window.
Using SendMessage(WM_SETTEXT) or SendMessage(EM_REPLACESEL) you could send a whole string at once to a particular window.

I'm not totally familiar with some of the API you're using, but I'm going to assume you're trying to send text to the stdin of some other process?
If it's a child process (i.e. one your process launched itself), you can use pipes and redirected I/O as explained in this article.

Related

Press a keyboard key by his char value C++

I would like to write a function that receives a char and presses it on the keyboard.
void pressKey(const char key){
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wVk = //What to put here? (receives WORD of the hex value)
ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));
}
How can I press the key 'a' (for example) and press it using this method or any other method?
When simulating keyboard input for text, you should use the KEYEVENTF_UNICODE flag to send Unicode characters as-is, use virtual key codes only for non-textual keys. And you need to send 2 input events per character, one event to press the key down, and one event to release it.
For example:
void pressKey(const char key){
INPUT ip[2] = {};
ip[0].type = INPUT_KEYBOARD;
ip[0].ki.wScan = key;
ip[0].ki. dwFlags = KEYEVENTF_UNICODE;
ip[1] = ip[0];
ip[1].ki.dwFlags |= KEYEVENTF_KEYUP;
SendInput(2, ip, sizeof(INPUT));
}
That being said, since this approach requires Unicode characters, if your key will ever contain a non-ASCII character then you will need to first convert it to Unicode UTF-16, such as with MultiByteToWideChar() or equivalent, and then you can send down/up events for each UTF-16 codeunit, as shown in this answer.

Simulate double direct keyboard input in C++

I found this c++ script that let you simulate a direct keyboard input, however, I need to simulate two inputs like [Ctrl + A]. I've been looking for ways to make it but I can't find the answer, if someone could help me or give me a clue I'd be grateful.
#include "stdafx.h"
#pragma comment(lib,"user32")
using namespace std;
int main()
{
char ch = 'a';
INPUT key;
memset(&key,0,sizeof(INPUT));//Zero the structure.
key.type = INPUT_KEYBOARD;
key.ki.dwExtraInfo = GetMessageExtraInfo();//<-- you will need to pinvoke this too.
key.ki.wScan =
static_cast<WORD>(MapVirtualKeyEx(VkKeyScanA(ch), MAPVK_VK_TO_VSC, GetKeyboardLayout(0)));//more pinvoking
key.ki.dwFlags = KEYEVENTF_SCANCODE;//<-- you will probably have to declare this constant somewhere-
//in your C# program.
//Ready to send the key-down event.
SendInput(1, &key, sizeof(INPUT));
Sleep(1000);//Wait one second before sending key-up.
//Sending key-up.
key.ki.dwExtraInfo = GetMessageExtraInfo();
key.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;//Key-up need be defined too, or just use the value.
SendInput(1, &key, sizeof(INPUT));
}
I've written this code, Ctrl press isn't working, however, 'W' press does.
int main()
{
Sleep(2000);
INPUT ip;
char key1 = VK_CONTROL, key2 = 'w';
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wScan = key1;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Press key2
ip.ki.wScan = key2;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release key2
ip.ki.wScan = key2;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
// Release key1
ip.ki.wScan = key1;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
I've noticed if I delete the VK_CONTROL press lines, 'W' press doesn't work neither.
int main() {
Sleep(2000);
INPUT ip;
char key2 = 'w';
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
// Press key2
ip.ki.wScan = key2;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release key2
ip.ki.wScan = key2;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}
To send a ctrl-a, you need to send, in order:
key-down events
VK_CONTROL
virtual code for a
key-up events
virtual code for a
VK_CONTROL
so, using VkKeyScanExW to get the virtual scan code for 'a'
key.ki.wVk = VK_CONTROL;
/* send keystroke */
key.ki.wVk = /* the virtual key code for a that you derived */
/* send keystroke */
/* set flag to keyup */
key.ki.wVk = /* Virtual code for a */
/* send keystroke */
key.ki.wVk = VK_CONTROL;
/* send keystroke */
where VK_CONTROL is the macro defined in Windows that gives you the keyboard virtual code for ctrl. Leave wScan set to 0.
You are sending virtual codes to the scan code parameter. The scan code for w is not 'w'.
In scan code set 1 (US keyboards), w's scan code is 0x11, and left control's scan code is 0x1D. Microsoft's Keyboard Scan Code Specification details sets 1 and 2, and can be found at https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc. There are commonly 3 sets of scan codes, and they are enumerated various places on the web. Or, you can use a utility to capture your own keyboard's scan codes. Sharpkeys or AutoHotkey appear to be popular utilities for doing just this.

How to highlight an entire word in C++?

I have made the following C++ program to highlight the last word before the cursor in a typing interface by sending Control+Shift+Left and then copy it to clipboard by sending Control+C.
#define WINVER 0x0500
#include <windows.h>
#include <Winuser.h>
using namespace std;int main() {
// Create a generic keyboard event structure
INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
while(true) {
if( GetKeyState(VK_LMENU) & 0x8000 ) {
Sleep(200);
// Press the "Ctrl" key
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Press the "Shift" key
ip.ki.wVk = VK_SHIFT;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Press the "Left" key
ip.ki.wVk = VK_LEFT;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release the "Left" key
ip.ki.wVk = VK_LEFT;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
// Release the "Shift" key
ip.ki.wVk = VK_SHIFT;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
// Press the "C" key
ip.ki.wVk = 'C';
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release the "C" key
ip.ki.wVk = 'C';
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
// Release the "Ctrl" key
ip.ki.wVk = VK_CONTROL;
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));
}}}
This is meant to work when I press the Left-Alt key. It works fine for words like abc or hello but not with words like #abc or hello%hello. I need to make it work for the entire word. By "entire word" what I mean is any collection of characters that does not include spaces or line breaks.
If you can't solve my problem completely, please know that I am open to workarounds that may work differently or include certain limitations. But I really this so please help.
And please feel free to suggest edits to help me improve this question.
As IInspectable mentioned, obviously what you consider to be a word and what the text field considers to be a word are two different things and you can't really do anything about it. So instead of trying to simulate the input which is not getting you what you want anyway, you should try and retrieve a handle (HWND) for the text field using some combination of FindWindowEx calls.
Now I can't exactly tell you how to find the window you need because I don't know where it is on your system and which application it belongs to. But you might be able to get the required information to do this (window hierarchy and class names) using some tool such as Inspect.
After that you should be able to get the text from the text field and parse it to get the first word:
#include <Windows.h>
int main()
{
/* You should adjust the following code to whatever criteria
you are using to choose the text field */
HWND appWindow = FindWindowEx(GetDesktopWindow(), NULL, NULL, "App window title");
HWND editControl = FindWindowEx(appWindow, NULL, "EDIT", NULL);
int size = GetWindowTextLength(editControl) + 1;
char *text = new char[size];
GetWindowText(editControl, text, size);
int cursorPos = 0;
SendMessage(editControl, EM_GETSEL, (WPARAM) &cursorPos, NULL);
for (int i = cursorPos; i < size; ++i) {
if (text[i] == ' ') {
text[i] = '\0';
break;
}
}
char *word = &text[cursorPos];
//do whatever you need with the word here
delete[] text;
return 0;
}
I didn't really have the opportunity to test this code and regarding copying the text to the clipboard: it seems to be a lot more complicated task to achieve using Win32 API which is in great detail described here.

How to print/press '#' using keybd_event function?

To press 'a' code is
keybd_event(VkKeyScan(64),0,0,0);
Releasing key code is
keybd_event(VkKeyScan(64),0,KEYEVENTF_KEYUP,0);
For pressing '#' i need combination of two key - SHIFT & 2 , but i don't know how.
keybd_event (https://msdn.microsoft.com/en-us/library/windows/desktop/ms646304(v=vs.85).aspx)
Try the following:
Press Shift
Press 2
Release 2
Release Shift
Addendum
I just checked my own code where I did the same thing... keybd_event is deprecated (as stated on the site you linked), you should use SendInput instead.
This are my two functions to send the key press and release:
void sendKeyDown(unsigned char keyCode)
{
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wVk = keyCode;
input.ki.dwFlags = 0;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
SendInput(1, &input, sizeof(INPUT));
}
void sendKeyUp(unsigned char keyCode)
{
INPUT input;
input.type = INPUT_KEYBOARD;
input.ki.wVk = keyCode;
input.ki.dwFlags = KEYEVENTF_KEYUP;
input.ki.time = 0;
input.ki.dwExtraInfo = 0;
SendInput(1, &input, sizeof(INPUT));
}
And this should then give you an #:
sendKeyDown(VK_SHIFT);
sendKeyDown(0x32);
sendKeyUp(0x32);
sendKeyUp(VK_SHIFT);
Please check the 0x32, I can't reliably test it at the moment to be the key 2.

Can you explain what each line of the C++ function is doing? It sends keystrokes but I am confused by how

I was making a program to send keystrokes to another window and I got it all working, but I had to go online and find a function to do the keystroke portion itself. It works but I have no idea what it is actually doing. Can someone comment each line of this function explaining what it's doing?
void GenerateKey(int vk, BOOL bExtended) {
KEYBDINPUT kb = {0};
INPUT Input = {0};
/* Generate a "key down" */
if (bExtended) { kb.dwFlags = KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
/* Generate a "key up" */
ZeroMemory(&kb, sizeof(KEYBDINPUT));
ZeroMemory(&Input, sizeof(INPUT));
kb.dwFlags = KEYEVENTF_KEYUP;
if (bExtended) { kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; }
kb.wVk = vk;
Input.type = INPUT_KEYBOARD;
Input.ki = kb;
SendInput(1, &Input, sizeof(Input));
return;
}
Here's an example of a call to it:
GenerateKey('C', FALSE); // Sends keystroke 'c'
This sends the keystroke 'c'.
This function only works with capital letters and seems to only work with specific hex codes. For example, to send a carriage return (enter key), here is the call:
GenerateKey(0x0D, FALSE); // Sends carriage return
However, if I try sending a question mark (hex 0x3F) with either of these calls, nothing happens:
GenerateKey(0x3F, FALSE); // Nothing happens
GenerateKey('?', FALSE); // Nothing happens
Can anyone see why those wouldn't work?
Also, can someone explain what the second argument, BOOL bExtended, is for? Changing between TRUE and FALSE seems to make no difference in the keystrokes it sends.
Your GenerateKey function makes internal use of the SendInput function from the Win32 API, which synthesizes keyboard input.
You can find all of the information you need to understand how that function works and how to call it by reading the MSDN documentation for that function.
The vk parameter is a virtual key code, listed here.
If the bExtended parameter is TRUE, then the KEYEVENTF_EXTENDEDKEY flag is set, which according to the documentation means that "the scan code was preceded by a prefix byte that has the value 0xE0 (224)".