I would like to simulate shortcuts for a remote control feature of our Windows Mobile application. Any possible shortcut should be supported (think of Ctrl+/ or Alt+ä).
With keybd_event I can simulate shortcuts very well, but only Virtual-Key Codes are allowed with this function. Therefore, I thought of the PostKeybdMessage function which allows me to send any character to the foreground window. But if I combine the two calls, Windows will just print the character instead of executing the shortcut.
Here’s what I tried:
- Sending the CTRL key silently (
KEYEVENTF_SILENT) - Adding the
KeyShiftAnyCtrlFlagto thePostKeybdMessagecall - Played a lot with the buffers and the flags of the
PostKeybdMessagecall (which is quite confusing)
My questions are:
- Can
PostKeybdMessagebe used to simulate shortcuts or am I just wasting my time? If it can, what did I do wrong in the code sample? - Is there maybe a trick to send special characters (umlauts, #, =, …) with
keybd_event? - Is there another way to simulate a shortcut?
Simple test application
public partial class ShortcutTest : Form
{
private const int KEYEVENTF_KEYUP = 0x0002;
private const int HWND_FOREGROUND = -1;
private const uint KEY_STATE_DOWN = 0x0080;
private const uint KEY_SHIFT_NO_CHARACTER = 0x00010000;
private const uint KEY_SHIFT_ANY_CONTROL = 0x40000000;
private const byte VK_CONTROL = 0x11; // Keys.ControlKey
[DllImport("coredll.dll", SetLastError = true)]
internal static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
[DllImport("coredll.dll")]
private static extern bool PostKeybdMessage(int hwnd, uint vKey, uint KeyStateFlags, uint cCharacters, uint[] pShiftStateBuffer, uint[] pCharacterBuffer);
public ShortcutTest()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
timer1.Enabled = false;
keybd_event((byte)Keys.ControlKey, 0, 0, 0);
// this would work: keybd_event((byte)Keys.X, 0, 0, 0);
// this won't work
SendChar('x');
//keybd_event((byte)Keys.X, 0, KEYEVENTF_KEYUP, 0);
keybd_event((byte)Keys.ControlKey, 0, KEYEVENTF_KEYUP, 0);
button1.Enabled = true;
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
button1.Enabled = false;
}
public void SendChar(char ch)
{
uint[] input = new uint[] { (uint)ch };
uint[] downStates = { KEY_STATE_DOWN | KEY_SHIFT_ANY_CONTROL };
uint[] upStates = { KEY_SHIFT_NO_CHARACTER | KEY_SHIFT_ANY_CONTROL };
PostKeybdMessage(HWND_FOREGROUND, 0, downStates[0], 1, downStates, input);
// tested with KeyShiftDeadFlag and some others, with \0 char ...
PostKeybdMessage(HWND_FOREGROUND, 0, upStates[0], 1, upStates, input);
}
}
Edit: I just looked up the OpenNETCF implementation of SendKeys and they use keybd_event only (so “+a” will fail for example).
Have you tried using SendInput? I am actually using c++, and following code:
generates messages that look like should work, I checked in spy on WM6.5.