How to programatically type a string in C++

Red Squirrel

No Lifer
May 24, 2003
70,356
13,680
126
www.anyf.ca
I'm writing a program to automate something and I need a way to make the computer type a string that is user inputted. I was looking at keybd_event but it seems this uses keyboard codes. I would need to write a ridiculously large switch statement so I can make it work with strings. Is there another way?
 

BRcr

Junior Member
Feb 14, 2013
12
0
0
Of course. You should just run a cycle through all characters in your string, calling keybd_event() for each one pressing it down and up(that's two calls!). And don't forget an interval between presses, as many programs wouldn't catch a fast input.
 

nickbits

Diamond Member
Mar 10, 2008
4,122
1
81
SendMessage with WM_CHAR WM_keydown or keybd_event are about it without going to 3rd party libraries. Also you can do keybd_event w/o a huge switch.
 

Red Squirrel

No Lifer
May 24, 2003
70,356
13,680
126
www.anyf.ca
Of course. You should just run a cycle through all characters in your string, calling keybd_event() for each one pressing it down and up(that's two calls!). And don't forget an interval between presses, as many programs wouldn't catch a fast input.

The keyboard codes != the ascii codes. So that does not work. I actually tried it without realizing then quickly realized it does not work.


VkKeyScan seems to sorta work, but only for keys that don't require shift. I suppose I cold hard code shift for the times I need it but I'm hoping to make a simple TypeString() function in my program that will type anything I throw at it.
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,663
4,603
75
You didn't elaborate on what Windows API you're using. Can you use SendKeys?
 

Red Squirrel

No Lifer
May 24, 2003
70,356
13,680
126
www.anyf.ca
Using standard API (not .net)

For vkkeyScan, what does this mean? Think it might be of importance for this to work well.

If the function succeeds, the low-order byte of the return value contains the virtual-key code and the high-order byte contains the shift state, which can be a combination of the following flag bits.

[list omitted]

For the return value. But isin't the return value what is fed to keybd_event()? I think this may have to do with why chars like !@#$%^&*() are returning numbers (1234567890) respectively. But what is "low order byte" and how do I get that and what do I do with that data?

This is way more complicated than it should be. Go Microsoft.
 
Last edited:

Merad

Platinum Member
May 31, 2010
2,586
19
81
For the return value. But isin't the return value what is fed to keybd_event()? I think this may have to do with why chars like !@#$%^&*() are returning numbers (1234567890) respectively. But what is "low order byte" and how do I get that and what do I do with that data?

Some characters require 2 keystrokes to generate. Like '!' (shift + 1). So, they pack two key values int one returned value. Google bitwise manipulation for how to get both values.

This is way more complicated than it should be. Go Microsoft.

Low level manipulation of the keyboard or other input devices isn't easy.
 

Red Squirrel

No Lifer
May 24, 2003
70,356
13,680
126
www.anyf.ca
Turns out someone already did the hard work, so ended up just using this:

Code:
void SendKeysWait(string text, int interval) 
{
	int ch;
	int ch2 = -1;
	bool SHIFTDOWN = 0;
	for (int i = 0; i<text.size(); i++) 
	{
		SHIFTDOWN= 0;
		switch (text[i]) 
		{
			case '\"':{ch = VkKeyScan('\"');ch2= VK_SHIFT; SHIFTDOWN = 1;} break;
			case '£': {ch = VkKeyScan('£');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '$': {ch = VkKeyScan('$');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '%': {ch = VkKeyScan('%');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '^': {ch = VkKeyScan('^');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '&': {ch = VkKeyScan('&');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '*': {ch = VkKeyScan('*');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '_': {ch = VkKeyScan('_');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '+': {ch = VkKeyScan('+');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '{': {ch = VkKeyScan('{');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '}': {ch = VkKeyScan('}');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '@': {ch = VkKeyScan('@');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '~': {ch = VkKeyScan('~');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '?': {ch = VkKeyScan('?');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '<': {ch = VkKeyScan('<');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '>': {ch = VkKeyScan('>');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '|': {ch = VkKeyScan('|');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case ':': {ch = VkKeyScan(':');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '!': {ch = VkKeyScan('!');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case '(': {ch = VkKeyScan('(');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			case ')': {ch = VkKeyScan(')');ch2 = VK_SHIFT; SHIFTDOWN = 1;} break;
			default:
			{
				if (text[i] >= 'A' && text[i] <= 'Z') 
				{
					ch = VkKeyScan( text[i]);
					ch2 = VK_SHIFT;
					SHIFTDOWN = 1;
				} else ch = VkKeyScan( text[i]);
			}
		}
		if (SHIFTDOWN) keybd_event(ch2, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
		keybd_event(ch, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
		Core->Sleep(interval/2);
		keybd_event(ch, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
		if (SHIFTDOWN) keybd_event(ch2, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
		Core->Sleep(interval);
	}
}



Some characters require 2 keystrokes to generate. Like '!' (shift + 1). So, they pack two key values int one returned value. Google bitwise manipulation for how to get both values.

Kind of what I was suspecting too, just not sure what they mean by low order, and not sure how many bits to grab, where to start, etc. It does not really do a good job at explaining that. Ex: if it's a 16 bit int, is the first 8 bits one key, and the other 8 bits another? etc
 

Merad

Platinum Member
May 31, 2010
2,586
19
81
Kind of what I was suspecting too, just not sure what they mean by low order, and not sure how many bits to grab, where to start, etc. It does not really do a good job at explaining that. Ex: if it's a 16 bit int, is the first 8 bits one key, and the other 8 bits another? etc

I'm a bit rusty but I believe this should do it.

Code:
bool getKeys(char ch, char& key, bool& shift, bool& ctrl, bool& alt)
{
  short temp = VkKeyScan(ch);
  
  key = (char) temp & 0x00ff;
  shift = temp & 0x0100;
  ctrl = temp & 0x0200;
  alt = temp & 0x0400;
  
  return key != -1;
}
 

Schmide

Diamond Member
Mar 7, 2002
5,731
1,023
126
Turns out someone already did the hard work, so ended up just using this:

(snip see above)

Kind of what I was suspecting too, just not sure what they mean by low order, and not sure how many bits to grab, where to start, etc. It does not really do a good job at explaining that. Ex: if it's a 16 bit int, is the first 8 bits one key, and the other 8 bits another? etc

Keyboard mapping is virtual so hard coding what keys are shifted above is kind o not cool. It will work on some machines but not work on others.

Showing a bit of code from

http://www.ffuts.org/blog/mapvirtualkey-getkeynametext-and-a-story-of-how-to/

Code:
std::string GetKeyName(unsigned int virtualKey)
{
    unsigned int scanCode = MapVirtualKey(virtualKey, MAPVK_VK_TO_VSC);

    // because MapVirtualKey strips the extended bit for some keys
    switch (virtualKey)
    {
        case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: // arrow keys
        case VK_PRIOR: case VK_NEXT: // page up and page down
        case VK_END: case VK_HOME:
        case VK_INSERT: case VK_DELETE:
        case VK_DIVIDE: // numpad slash
        case VK_NUMLOCK:
        {
            scanCode |= 0x100; // set extended bit
            break;
        }
    }

    char keyName[50];
    if (GetKeyNameText(scanCode << 16, keyName, sizeof(keyName)) != 0)
    {
        return keyName;
    }
    else
    {
        return "[Error]";
    }
}

You can see how MapVirtualKey translates to the scancode for the key. You should be able to change GetKeyNameText with two keybd_event calls as shown in your code listings to get the desired effect.
 

Red Squirrel

No Lifer
May 24, 2003
70,356
13,680
126
www.anyf.ca
On this subject, anyone know what it means when there's two numbers listed for the virtual key codes? ex:

Home E0 47
End E0 4F
Up Arrow E0 48
Dn Arrow E0 50
Page Up E0 49
Page Down E0 51
R Arrow E0 4D

Where do I put E0 and 47? Normally this number goes into the first parameter, but what if there's two?

Also where can I get a list of VK codes such as VK_NUMLOCK?

I need to simulate home + hold down shift + end + let go shift + delete. Might be easier to do this with the VK type codes vs the numeric ones. They just don't seem to have a list for those.