Introduction
The Windows keybd_event
mechanism is useful in many ways, specially in automation of tasks such as entering input etc. But its capability is restricted by the fact that it can be a little tedious for entering large number of key combinations which can be variable and which cannot be programmed easily. So I have done all the dirty work for you. You have to just include the class I provide in your program, and then you can form a script and use the class methods to run the script. This script can be used to automate any task that can be accomplished using the keyboard. This can be a real blessing if you are as lazy as I am. Also, the CreateProcess
method is used for creating new processes like Winamp, IE etc.
Elementary keybd_event and CreateProcess
According to MSDN the keybd_event
function synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP
or WM_KEYDOWN
message. The keyboard driver's interrupt handler calls the keybd_event
function. For example, if you want to simulate the pressing of the Enter key, then you have to use the keybd_event
once for pressing down the key and then again for releasing the key, like in the example given below:
keybd_event(VK_RETURN, 0, 0, 0);
::Sleep(50);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
In order to simulate the pressing of a key combination like ALT+ENTER, you have to first press down ALT, then press ENTER, then release ENTER, and then release ALT, like below:
keybd_event(VK_MENU, 0, 0, 0);
::Sleep(50);
keybd_event(VK_RETURN, 0, 0, 0);
::Sleep(50);
keybd_event(VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
::Sleep(50);
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
VK_MENU
and VK_RETURN
are the codes for the ALT and ENTER keys. Instead of the virtual key code, you can also pass the corresponding hex values. An official table containing the keys and their codes is given here.
CreateProcess
can be used to create a new application or process by passing its executable file as a parameter. Its usage is been given below, and the example opens a new Notepad window.
TCHAR szCmdline[]=TEXT("notepad");
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi) );
CreateProcess( NULL,
szCmdline,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi ) ;
After creating the process, if you want to pass any keyboard input to it, then you will have to first set focus on the newly created process. This can be done by using the SetFocus
function which requires HWnd
as an argument. The handle of the newly created process can be obtained from the process ID by using enum Windows
. A good implementation class has been provided here so you can use code like below to set focus to the window after creating the application:
DWORD pid = pi.dwProcessId;
CMainWindowIterator itw(pid);
for (HWND hwnd = itw.First(); hwnd; hwnd=itw.Next())
{
SetFocus(hwnd);
break;
}
Basic Key Presses
Now, let's say that you want to simulate the pressing of a key. You just have to use the function RunKey()
like below:
VirKey vk;
com="do";arg="TAB";times=2;sleep=300;
vk.RunKey(com,arg,times,sleep);
This function call will press, or more correctly simulate the pressing of, the key TAB twice in a 300 ms interval. The com
parameter (character string) means the command you want to execute. Currently, two kinds of commands are implemented: "do
" and "open
". do
can be used to to enter any key combination. open
can be used to open any application.
Now, the arg
parameter (character string) is in accordance with com
. If com
is do
, then arg
contains the code for a particular key, like TAB (an account of all keys supported along with their codes is given in the codes.txt file in the source code and binary release). If com
is open
, then arg
is a character string containing the full path name of the application executable to be created, like, for IE, the default should be "C:\Program Files\Internet Explorer\IEXPLORE.EXE". If your path contains spaces in between, like the case above, then make sure that your path is specified in double quotes as shown above, as this is directly passed to the CreateProcess
method. times
(integer) specifies the number of times the do
or open
command has to be executed, and sleep
(integer) denotes the time in msec between consecutive commands.
Converting a String into a Sequence of Key Presses
Now, if you want to send a string as a sequence of key presses and think that the previous function is also tedious, then this section may interest you. If your application requires entering a particular word, then you can use the Runstring()
function as given below:
VirKey vk;
vk.Runstring("Hello You!!!");
The whole string will be converted into key presses. Caution: The string function will work with only standard characters and not with special keys like TAB, ALT etc.
Making Scripts
Now, this is the part from where the real fun starts. If you have a large task or key presses to perform, then you can use the script feature. Let's discuss the script first. The script is sequential in nature with an easy syntax. Each line in the script has four parts, similar to the parameters of the RunKey()
above: command
, argument
, times
, and sleep
. The caution to maintain here is that argument
should end with a $. For example, to open Internet Explorer and then to press Enter, your script would look like below:
open "C:\Program Files\Internet Explorer\IEXPLORE.EXE"$ 1 4000
do RETURN$ 1 200
Along with the normal commands open
and do
, an additional command called string
has been added. It can be used to enter strings:
string Hello!!$ 1 100
Now, when your script is prepared, you have to process it to prepare a file which contains the hexcode instead of key codes. This file is loaded, run-time interpreted, and run. This saves time and resources during running, and is similar to compilation and execution. To process a given script file, you can use the ES2S()
function. This function takes two arguments (character strings): the source script file name and the script name. For example, to prepare the script hello from Scriptfile.txt, the function is called as:
VirKey vk;
vk.ES2S("Scriptfile.txt","hello");
Now, if your script is prepared, you might feel a strong urge to run it, in which case you have to use the Runx()
function which takes as an argument the name of the script. Hence:
VirKey vk;
vk.Runx("hello");
Composite Key Presses
Your application might want to keep composite key combinations such as ALT+F4. For this purpose, support has been added for the composite key press of ALT, SHIFT, CTRL, and WIN. So, you just have to enter ALT+F4 as arg
in the RunKey
function or your script.
Caution: If you are planning to use 2-3 composite combinations like SHIFT+CTRL+DEL, then it will be a good idea to follow the order ALT, then CTRL, then SHIFT, then WIN. Like ALT+CTRL+f or CTRL+SHIFT+C etc. You should get the idea.
Application
A sample application has been provided as demo. Using the application is extremely easy. First, you have to prepare a script which you want to run. Let's say you want to open an Internet Explorer window and then automatically open Yahoo! mail and login into your account. Then, if you don't have any homepage set and have no proxy authentication while accessing the internet, your script should look like the one below:
open "C:\Program Files\Internet Explorer\IEXPLORE.EXE"$ 1 4000
do TAB$ 1 200
string http://mail.yahoo.com$ 1 1000
do RETURN$ 1 4000
string username$ 1 100
do TAB$ 1 100
string password$ 1 100
do RETURN$ 1 200
After you prepare a script, save it in a file and open the application provided above. Click on "New Script File". A File Open dialog box will appear. Select your script file, and enter the name of the script by which you want it to run, e.g., "login". Then, press "Make Script"; your script will be processed .Then, enter the name you provided in the script, e.g., "login" in the first editor, and click on "Execute", and then don't touch your keyboard or mouse, and the script will start executing, opening an IE window, opening Yahoo!, and then logging in.
Conclusion
To conclude, if you would like to incorporate the class in your application, then just add Virkey.cpp, VirKey.h, WindowIterator.cpp, and WindowIterator.h in your code. I would like to thank Paul DiLascia for using his class for getting the process handle from the process ID, and also would like to sincerely apologize for the inhuman atrocities committed by me on the English language. If you find the class useful, then please feel free to drop your questions, suggestions, problems, and bugs at my mail address; otherwise, if the only thing you can think of are curses for me, then I am also searching for the moron who wrote this article.