I am writing a C# program which captures signals from a external device, and sends keystrokes to another application. I am using SendKeys and it works fine.
SendKeys does "press" a key by holding and releasing it immediately. I would like to make it push key and release it at will.
My question is : "is there a way to send a "push" signal to a key, then a "release" signal after a certain amount of time ?"
I am not sure SendKeys is able to do this. Any clue ?
I don't think it's possible from .NET directly You could try using keybd_event native call by p/invoking the function as described here: http://pinvoke.net/default.aspx/user32.keybd_event
The MSDN for keybd_event is here: http://msdn.microsoft.com/en-us/library/ms646304(VS.85).aspx
Hope that helps!
The accepted answer uses keybd_event
which is deprecated. The official API is now SendInput
. There's also a nice wrapper for it at http://inputsimulator.codeplex.com.
None of the above, however, fully caters to the "key holding" scenario. This is due to the fact that holding a key will generate multiple WM_KEYDOWN
messages, followed by a single WM_KEYUP
message upon release (you can check this with Spy++).
The frequency of the WM_KEYDOWN
messages is dependent on hardware, BIOS settings and a couple of Windows settings: KeyboardDelay
and KeyboardSpeed
. The latter are accessible from Windows Forms (SystemInformation.KeyboardDelay
, SystemInformation.KeyboardSpeed
).
Using the aforementioned Input Simulator library, I've implemented a key holding method which mimics the actual behavior. It's await/async
ready, and supports cancellation.
static Task SimulateKeyHold(VirtualKeyCode key, int holdDurationMs,
int repeatDelayMs, int repeatRateMs, CancellationToken token)
{
var tcs = new TaskCompletionSource<object>();
var ctr = new CancellationTokenRegistration();
var startCount = Environment.TickCount;
Timer timer = null;
timer = new Timer(s =>
{
lock (timer)
{
if (Environment.TickCount - startCount <= holdDurationMs)
InputSimulator.SimulateKeyDown(key);
else if (startCount != -1)
{
startCount = -1;
timer.Dispose();
ctr.Dispose();
InputSimulator.SimulateKeyUp(key);
tcs.TrySetResult(null);
}
}
});
timer.Change(repeatDelayMs, repeatRateMs);
if (token.CanBeCanceled)
ctr = token.Register(() =>
{
timer.Dispose();
tcs.TrySetCanceled();
});
return tcs.Task;
}
You could use SendInput or keyb_event, both are native API functions. SendInput has some advantages over keybd_event, but SendInput is only available starting with XP.
Here is the msdn link http://msdn.microsoft.com/en-us/library/ms646310.aspx
Hope this helps
I once was looking to do the same thing on powerpoint, to hide the cursor, and later to stop the slideshow. But it's hard and tricky as there's many top level windows appeared in powerpoint, also it's hard to figure out which part of the emulation failed if it doesn't work. After looking into the message queue using Spy++, I notice that the accelerator command was sent after the keypress, so instead, I emulated the accelerator command, and it works like charm. So you might want to look into alternative like this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With