La respuesta aceptada usa keybd_event
que está en desuso. La API oficial ahora es SendInput
. También hay una buena envoltura para él en http://inputsimulator.codeplex.com.
Ninguno de los anteriores, sin embargo, satisface completamente el escenario de "retención de tecla". Esto se debe al hecho de que mantener presionada una tecla generará múltiples mensajes WM_KEYDOWN
, seguidos de un mensaje único WM_KEYUP
al momento de la publicación (puede verificar esto con Spy ++).
La frecuencia de los mensajes WM_KEYDOWN
depende del hardware, la configuración del BIOS y un par de configuraciones de Windows: KeyboardDelay
y KeyboardSpeed
. Los últimos son accesibles desde Windows Forms (SystemInformation.KeyboardDelay
, SystemInformation.KeyboardSpeed
).
Utilizando la biblioteca de Input Simulator mencionada, he implementado un método de retención de teclas que imita el comportamiento real. Está await/async
listo, y admite la cancelación.
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;
}
¡Guau! Funcionó bien para mí Muchas gracias ! – Larry