Simulating keystrokes
by Kent Reisdorph
Sometimes an application needs to simulate keystrokes that are normally performed by the user. There could be a variety of reasons to simulate keystrokes. For example, you may need to dismiss a menu the user has open or take a screenshot of the application for technical support reasons. Or maybe you are creating an automated tutorial that guides the user through a particular sequence. These actions can be accomplished by simulating keystrokes.
The keybd_event() function
There are several ways to go about simulating keystrokes, but the simplest and most effective is to use the Win32 API keybd_event() function. This function is declared as follows:
VOID keybd_event(BYTE bVk, BYTE bScan, DWORD dwFlags, DWORD dwExtraInfo);
The first parameter, bVk, is used to specify the virtual key code of the key you wish to simulate. (I will explain this parameter in more detail in the next section). The bScan parameter is used to pass the hardware scan code for the key. You should pass 0 for this parameter. The dwFlags parameter is used to specify whether the key is being pressed or whether it is being released. Pass 0 for this parameter if you are simulating a key press, or KEYEVENTF_KEYUP if you are simulating the release of a key. The dwExtraInfo parameter is used to pass any application-specific data associated with the key press. You won’t typically use this parameter in a VCL application so you can simply pass 0.
Specifying the key code
As I have said, the first parameter of keybd_event() is used to pass the value of the key for which you are simulating a key press. You can pass virtual key codes to keybd_event() in one of two ways: using one of Windows’ virtual key codes, or the ASCII value corresponding to an alphanumeric key. Let’s say, for example, that you wanted to simulate the press of the Enter key. In that case you would use this code:
keybd_event(VK_RETURN, 0, 0, 0); keybd_event( VK_RETURN, 0, KEYEVENTF_KEYUP, 0);
In this example, the virtual key constant passed is VK_RETURN, the value that corresponds to the Enter key. The Windows virtual key constants can be found by looking at the topic, “Virtual-Key Codes” in the Win32 help file. Be aware, though, that this help topic is not entirely accurate. For example, it states that the virtual key codes for alpha keys are VK_A through VK_Z. In reality, these virtual key codes no longer exist in the Windows headers. For the ultimate source of information on virtual key codes, see the WINUSER.H header that ships with C++Builder.
Note that the preceding code calls keybd_event() once for the key press, and once for the key release. If you don’t call keybd_event() for the key release, your application may exhibit strange behavior. For example, if you call keybd_event() to simulate an Alt key press and do not call keybd_event() a second time to simulate release of the Alt key, the application will behave as if the Alt key were stuck down.
To simulate the press of an alpha key, pass the ASCII value of the upper case letter for that key:
keybd_event('M', 0, 0, 0);
keybd_event(
'M', 0, KEYEVENTF_KEYUP, 0);
You must pass the letter in upper case or the function will fail. Even though the ASCII value for an upper case m is passed, the actual key code sent to Windows will depend on what other keys are down. If the Shift key is down when this code executes, an upper case m will be sent to Windows. An upper case m will also be sent to Windows if Caps Lock is on when this code executes.
Uses of keybd_event()
You might need to simulate a keystroke in any number of situations. The specific reasons for simulating a keystroke are application-specific. However, I will illustrate the use of keybd_event() with a few examples.
Simulating menu selections
One case where you may want to simulate key presses is to emulate programmatically what the user may do manually. For example, assume that you have an application with a standard File menu. The keystrokes for choosing File|New are Alt-F-N (assuming the default accelerator keys). The code to simulate this key combination is:
// simulate Alt key press
keybd_event(VK_MENU, 0, 0, 0);
// simulate F key press
keybd_event('F', 0, 0, 0);
// release F key
keybd_event('F', 0, KEYEVENTF_KEYUP, 0);
// release Alt key
keybd_event(
VK_MENU, 0, KEYEVENTF_KEYUP, 0);
// press and release N key
keybd_event('N', 0, 0, 0);
keybd_event('N', 0, KEYEVENTF_KEYUP, 0);
You may have noticed from this code that the virtual key code for the Alt key is VK_MENU. There is no VK_ALT virtual key code as you might expect. Note that each key press is followed by code that simulates a key release.
Dismissing a menu
Users are known for doing things with your application that you don’t expect. For example, a user may drop down a menu and go for a cup of coffee. If your application needs to do processing on a periodic basis, the fact that the menu is dropped down may interfere with that processing. You can easily dismiss a menu that is showing by sending an Esc key press to the application. The code for doing this is simple:
keybd_event(VK_ESCAPE, 0, 0, 0); keybd_event( VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0);
You may want to follow this code with a second Esc key press in case the top-level menu item is still selected.
Grabbing a screen shot
You can easily take a screen shot of the desktop by simulating a Print Screen key press, or a screen shot of the active window by simulating an Alt-Print Screen key press. Here’s how the code looks for getting a screen shot of the active window:
keybd_event(VK_MENU, 0, 0, 0); keybd_event(VK_SNAPSHOT, 0, 0, 0); keybd_event( VK_SNAPSHOT, 0, KEYEVENTF_KEYUP, 0); keybd_event( VK_MENU, 0, KEYEVENTF_KEYUP, 0);
Note that this code first sends the Alt keystroke to the application and then the Print Screen keystroke (the VK_SNAPSHOT constant is used for the Print Screen key). The documentation for keybd_event() explains another way to accomplish this. It says that you can pass 0 for the second parameter to get a screen shot of the entire desktop, or 1 to get a screen shot of the active window.
Once you have the screen shot image in the clipboard you can easily save it to a file on disk using this code:
Sleep(1000);
Graphics::TBitmap* bm =
new Graphics::TBitmap;
bm->Assign(Clipboard());
bm->SaveToFile("d:\\test.bmp");
delete bm;
Note that I have introduced a slight delay to ensure that the entire image is in the clipboard prior to saving the image. This is a low-tech way to go about this. You will probably want to implement a more robust method in your own applications.
Demo animations
Another possible use of keybd_event() is in creating demo animations for your users. You can move the mouse cursor using a combination of GetCursorPos() and SetCursorPos(). You can then use keybd_event() to simulate button or menu clicks. I won’t go into further detail on this subject, but the example program for this article shows a simple demo animation effect.
Conclusion
Simulating keystrokes can be valuable for certain types of applications. The keybd_event() function provides a simple and effective way of simulating keystrokes. In addition to keybd_event(), Windows also has a mouse_event() function that can be used to simulate mouse events.
The example application for this article shows several uses of keybd_event(). First, it automatically dismisses the main menu if it is left open for three seconds. Second, allows the user to take a screen shot of the application’s main window. Third, it clicks a button on the form called “Test” using that button’s accelerator key. Finally, it provides a demo animation that “clicks” the File | New menu item. Download and examine the example program to see how these effects are implemented.