2008-10-05 16 views
8

Piszę program C#, który przechwytuje sygnały z urządzenia zewnętrznego i wysyła naciśnięcia klawiszy do innej aplikacji. Używam SendKeys i działa dobrze.Jak nacisnąć klawisz i zwolnić go za pomocą C#?

SendKeys naciska klawisz, natychmiast go przytrzymując i zwalniając. Chciałbym zrobić to naciskając klawisz i uwolnić go do woli.

Moje pytanie brzmi: "czy istnieje sposób wysłania sygnału" pchania "do klucza, a następnie" zwolnienia "sygnału po upływie określonego czasu?"

Nie jestem pewien, czy SendKeys jest w stanie to zrobić. Jakaś wskazówka?

Odpowiedz

1

kiedyś szukał zrobić to samo na PowerPoint, aby ukryć kursor, a później, aby zatrzymać pokaz slajdów. Ale jest to trudne i trudne, ponieważ w Power Point pojawiło się wiele okien najwyższego poziomu, a także trudno jest określić, która część emulacji zakończyła się niepowodzeniem, jeśli nie zadziała. Po sprawdzeniu kolejki komunikatów za pomocą Spy ++ zauważam, że polecenie akceleratora zostało wysłane po naciśnięciu klawisza, więc zamiast tego emulowałem polecenie akceleratora i działa ono jak charm. Więc możesz chcieć przyjrzeć się takiej alternatywie.

4

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; 
} 
+0

Dziękuję bardzo za ten cenny wkład. – Larry

+0

Nie ma za co, cenny wkład jest tym, o co w tym wszystkim chodzi;) –

Powiązane problemy