• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

How to programatically type a string in C++

Red Squirrel

No Lifer
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?
 
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.
 
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.
 
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.
 
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:
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.
 
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
 
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;
}
 
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.
 
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.
 
Back
Top