SRL Archive - C/C++ Help and Tutorials

KeyDown In C++


TravisV10

2007-08-06 15:01:26

Title

cathering_

2007-08-06 15:46:16

Google It :)

http://www.google.co.uk/search?hl=en&q=keydown+in+c%2B%2B&meta=

arcix

2007-08-12 12:24:59

There is a Windows API called SendInput that you can use to inject mouse, keyboard, and other device input into the foreground window.

Here is the MSDN syntax:

UINT SendInput(
UINT nInputs,
LPINPUT pInputs,
int cbSize
);

pInputs is an array of INPUT structures, nInputs is the number of structures used from the pInputs array, cbSize is the size of an INPUT array

INPUT structure definition:

typedef struct tagINPUT {
DWORD type;
union {MOUSEINPUT mi;
KEYBDINPUT ki;
HARDWAREINPUT hi;
};
}INPUT, *PINPUT;

To send keys, set type equal to INPUT_KEYBOARD and set up the KEYBDINPUT struct (yes, there are a lot of structures involved in this, heh)

KEYBDINPUT definition:

typedef struct tagKEYBDINPUT {
WORD wVk;
WORD wScan;
DWORD dwFlags;
DWORD time;
ULONG_PTR dwExtraInfo;
} KEYBDINPUT, *PKEYBDINPUT;

You can specifiy the key using either wVk, a virtual-key code, or wScan, the scan code. I recommend using the VK code. If you are sending a keydown message, set dwFlags to 0, if you are sending a keyup, set dwFlags to KEYEVENTF_KEYUP. Don't worry about dwExtraInfo or time, set them equal to 0.

That might all be confusing, especially if you aren't too familiar with structs/C++ syntax. Here is an example function that sends a keydown and then a keyup to the current window:

#include <windows.h> // this is a window API function we are using, so we
// must include windows.h and link with user32.lib
// (in the linker options of your compiler)

// Function SendKey
//
// Returns a UINT (unsigned integer),
//
// takes parameter:
// WORD virtual_key ( 2 bytes, specifies the key to simulate )
//

UINT SendKey(WORD virtual_key)
{
INPUT input[2]; // Initialize an input structure array of size 2,
// because we need to send 2 simulated keystrokes,
// one up and one down

KEYDBINPUT kbdUp,kdbDown; // Initialize 2 keydbinput structures,
// 1 for keydown and 1 for keyup

kbdDown.time=kbdUp.time=kbdDown.dwExtraInfo=kbdUp.dwExtraInfo=0;

kbdDown.wVk = kdbUp.wVk = virtual_key; // Set the wVk member

kbdDown.dwFlags = 0; // Keyup flag is not set
kbdUp.dwFlags = KEYEVENTF_KEYUP; // Keyup flag is set

input[0].type=input[1].type=INPUT_KEYBOARD; // Set up the input structs
input[0].ki = kbdDown; // Send down first
input[1].ki = kdbUp; // Send up next

return SendInput(2,(LPINPUT)input,sizeof(INPUT)); // call SendInput

// Will return 2 (# of keystrokes injected) on success or 0 on failure
}

There are alternate ways of doing this:

On a lower level, there are keyboard drivers that intercept and simulate keypresses before they even reach Windows. They are extremely powerful and allow for simulation of such things as key-holding. Kernel drivers, however, are far beyond the scope of this reply, and I don't recommend trying to write one if you don't know what you are doing (you will at the very least get a BSOD if you try to run a buggy driver)

On a higher level, you can send keystrokes with the SendMessage API. The advantage of this method is that you can pick the window to send messages to, even if it does not have keyboard focus (it is in the background). However, it is easy for a program to tell that these kind of messages are injected and ignore them.

Hopefuly, that is all you need to know about keystroke simulation in C++. For more information on the API functions used (SendInput,SendMessage), go to www.msdn.com.