Przyjęta odpowiedź używa keybd_event
, która jest przestarzała. Oficjalny interfejs API to teraz SendInput
. Jest tam również ładne opakowanie na http://inputsimulator.codeplex.com.
Żadne z powyższych nie w pełni uwzględnia scenariusz "trzymania klucza". Wynika to z faktu, że przytrzymanie klawisza wygeneruje wiele wiadomości WM_KEYDOWN
, a po wydaniu pojawi się jeden komunikat WM_KEYUP
(można to sprawdzić za pomocą Spy ++).
Częstotliwość wiadomości WM_KEYDOWN
zależy od sprzętu, ustawień systemu BIOS i kilku ustawień systemu Windows: KeyboardDelay
i KeyboardSpeed
. Te ostatnie są dostępne z Windows Forms (SystemInformation.KeyboardDelay
, SystemInformation.KeyboardSpeed
).
Korzystając z wyżej wymienionej biblioteki Input Simulator, zaimplementowałem metodę trzymania klucza, która naśladuje faktyczne zachowanie. Jest gotowy await/async
i obsługuje anulowanie.
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;
}
Nice! Sprawdziło się dla mnie dobrze. Dziękuję Ci bardzo ! – Larry