Introduction

One day I needed to send keys to another application in order to automate a task from my C++ program, but after some research, I found no easy way to do that in C++ and all what was found is reference to VB's or C#'s SendKeys. However, one of the search results returned sndkeys32.pas which is a Delphi code version of the SendKeys() written by Ken Henderson back in 1995.

Since I know Delphi and wanted this same functionality in C++, I decided to port and enhance the code to make it fit my needs. The remainder of the article will explain the concept of sending keys in Win32 and will show you how to use the code in order to send keys in just two lines of code!

Hope you find this article useful.

Key sending concept in Win32

The core functionality of sending keys in CSendKeys revolves around the usage of the keybd_event() Win32 API function.

The keybd_event() produces a keystroke, however the keyboard driver's interrupt handles the calls to this function, which means we can send almost any key combination with less limitations.

In brief, it allows you to send a virtual key, defined in winuser.h as VK_XXX, and a flag which denotes a KeyDown, KeyUp or state to tell if the VKey is an extended key or not.

Normal characters are translated into virtual keys using the VkKeyScan() which takes a CHAR and returns a WORD denoting a VK.

When you send a key, it will be depressed until you send it again with the KEYEVENTF_KEYUP flag.

CSendKeys is designed in a way to maintain certain compatibility with C#'s SendKeys while also adding more functionality. So if you used C#'s SendKeys.Send() or VB's before then using CSendKeys becomes easier.

Each key is represented by one or more characters. To specify a single keyboard character, use the character itself. For example, to represent the letter 'a', pass in the string "a" to the method. Naturally to represent a string of characters just pass them in order as "hello".

If you want to send modifier keys such as the SHIFT, ALT, CONTROL or WINKEY keys in addition to normal keys, you might want to use any of the characters defined in Table 3.

For example, if you want to send "A" you usually press Shift+A, which is equivalent to sending these key strokes: "+a" , similarly to send the "~" you would press Shift+` which is equivalent to key strokes "+`" or simply "{TILDE}" (Table 1.b).

All characters in Table 3 are reserved and have special meaning in addition to the left/right parenthesis/braces.

The parenthesis are used to associate a given modifier or modifiers with a group of characters, for example to send the "HELLO", you would describe as "+(hello)" which informs CSendKeys to depress the SHIFT key while sending the following keys group. Whereas the braces are used to enclose any of the keys displayed in Table 1 and 2.

The sent keys are sent to no specific application, instead they are just pressed and whatever application has the keyboard input will take the keys.

In order to send the keys to a specific window/application please use either of the methods:

// 1. activate an application using its handle
sk.AppActivate(hWnd);
// 2. activate an application given its window title
sk.AppActivate("Title");
/// 3. activate an application given either or both of its window title/class
sk.AppActivate(NULL, "TheClass"); // NULL means this criteria is not avail
// 4. via SendKeys method
sk.SendKeys("{appactivate Notepad}hello");

The following table is a slightly modified version of the MSDN/SendKeys help:

Key

Code

BACKSPACE

{BACKSPACE}, {BS}, or {BKSP}

BREAK

{BREAK}

CAPS LOCK

{CAPSLOCK}

DEL or DELETE

{DELETE} or {DEL}

DOWN ARROW

{DOWN}

END

{END}

ENTER

{ENTER} or ~

ESC

{ESC}

HELP

{HELP}

HOME

{HOME}

INS or INSERT

{INS}

LEFT ARROW

{LEFT}

NUM LOCK

{NUMLOCK}

PAGE DOWN

{PGDN}

PAGE UP

{PGUP}

PRINT SCREEN

{PRTSC} (reserved for future use)

RIGHT ARROW

{RIGHT}

SCROLL LOCK

{SCROLL}

TAB

{TAB}

UP ARROW

{UP}

F1

{F1}

F2

{F2}

F3

{F3}

F4

{F4}

F5

{F5}

F6

{F6}

F7

{F7}

F8

{F8}

F9

{F9}

F10

{F10}

F11

{F11}

F12

{F12}

F13

{F13}

F14

{F14}

F15

{F15}

F16

{F16}

Keypad add

{ADD}

Keypad subtract

{SUBTRACT}

Keypad multiply

{MULTIPLY}

Keypad divide

{DIVIDE}

(table 1.a)

The following are my additions:

Key

Code

+

{PLUS}

@

{AT}

APPS

{APPS}

^

{CARET}

~

{TILDE}

{ }

{LEFTBRACE} {RIGHTBRACE}

( )

{LEFTPAREN} {RIGHTPAREN}

Left/Right WINKEY

{LWIN} {RWIN}

WINKEY

{WIN} equivalent to {LWIN}

(table 1.b)

In addition to this, I have added some special keys that act like commands:

Command Syntax

Action

{VKEY X}

Sends the VKEY of value X.

Very useful if you don't want to recompile CSendKeys and add new Vkey to the hardcoded special keys table.

For example, {VKEY 13} is equivalent to VK_RETURN.

{BEEP X Y}}

Beeps with a frequency of X and a duration of Y milliseconds.

{DELAY X}

Delays sending the next key of X milliseconds. After the delaying the following key, the subsequent keys will not be further delayed unless there is a default delay value (see DELAY=X).

Example: {DELAY 1000} <-- delays subsequent key stroke for 1 second.

{DELAY=X}

Sets the default delay value to X milliseconds. This will cause every key to be delayed X ms.

If a value is already set and you specify {DELAY Y} you will have your following key delay Y ms but the subsequent keys will be delayed X ms.

Example: {DELAY=1000} <-- all subsequent keys will be delayed for 1 second.

{APPACTIVATE WindowTitle}

Activates an application using is WindowTitle.

Very useful if you want to send different keys to different applications.

Reference

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Thank you for providing this code, it is very useful! However, I found two problems with AppActivate() by window title and class name:

First, this line does not work correctly when compiling for Unicode, leaving garbage in "titleclass" and causing grief later in the search:

memset(titleclass, 0, l1 + l2 + 5);

Should be modified to:

memset(titleclass, 0, (l1 + l2 + 5)*sizeof(TCHAR));

Second, the code in CSendKeys::enumwindowsProc() seems to match any window of the given class name (if wclass is not NULL), regardless of window title provided. The code as provided in this article is:

In reading through the description above, it is not clear if the {DELAY 50} syntax just delays the onset of the next key to the KB buffer or whether it holds down the current key for 50ms. The original keyboard_event where you have to specify keydown and then keyup allows you to do this. I have a gaming application where I want to actually "press a key and hold it down until I release it" rather than repeatedly pressing it. Is this possible with Sendkeys C++?

Hiya guys, I had some problems with the ESC key.
Just so you know, when you want to send ESCAPE to a program, This library will send a WM_KEYDOWN message with the parameter Extended set to 0, BUT it will send a WM_KEYUP message with the parameter Extended set to 1!

it caused some problems with one particular program I wanted to control by getting stuck in a loop.

Quick Hotfix:
I changed sendkeys.cpp by removing any references to the KEYEVENTF_EXTENDEDKEY flag so that it will never set this flag to 1 (I loose control of some keys but in my particular case, it does not matter).

Please do not cross-post (or double-post), pick either here or the Lounge, not both.

Peace!

-=- JamesPlease rate this message - let me know if I helped or not!If you think it costs a lot to do it right, just wait until you find out how much it costs to do it wrong!Remember that Professional Driver on Closed Course does not mean your Dumb Ass on a Public Road!See DeleteFXPFiles

We're writing a Visual C++ application which needs to emulate key-strokes upon a particular event. We've downloaded the code from this sample.

When we add a reference to this project in our Visual C++ project (in Visual Studio .NET 2003) and include the header-files using "#include "SendKeys.h", it gives compilation errors saying "unresolved external symbol public: bool __thiscall CSendKeys::SendKeys". We've also tried importing all the code of the attached project into our project and compiling it from scratch. However, this option does not work as well (though the attached project compiles independently).

Can somebody pls let me know the sequence of steps that we need to follow to include this in our code (separate project) and compile it?

Just so that everyone knows. The C# SendKeys() doesn't work on DOS mode programs like EDIT.COM but this project does. I converted the entire thing to C#. Its not perfect because I don't know how to do proper marshalling of structs for the enumwindowsProc, but it does work properly (since I'm using FindWindow()/FindWindowEx()).

Your article is very very good,no doubt you have done increditable work and made
easy many peoples life like me.
I included your sendkey class .h and .cpp file in project on which I am working but it gives error at INPUT function, and SendInput function. That file is User32.lib file or in windows.h header or winuser.h . I included these files, but it gives error global function not declared. I dont know how to use.
One more thing
in AppActivate function you have written at a place ::SetForeGroundWindow(hwnd)
without which code doesnot give result,but for my application it is unwanted,as
I am behind removing unwanted MessageBox which Earlier engineer left in his dll whos
code is not with me.And I found I can work out well because of your contribution
to universal code.Will you please let me know,how to solve these problems.