Wie kann ich programmgesteuert Tastendruckereignisse in C # generieren?

107

Wie kann ich programmgesteuert ein Ereignis erstellen, das das Drücken einer Taste auf der Tastatur simuliert?

Dan Vogel
quelle
6
Benötigen Sie nur das Ereignis, um zu feuern?
Daniel A. White
Ich denke, Sie müssten in nicht verwalteten Code eintreten, um einen "echten" Tastendruck zu simulieren.
Jonas B
Ja, ich brauche nur das Ereignis, um zu feuern.
Dan Vogel
1
@ Goneale: Wow, ein drei Jahre alter Kommentar. OK dann. Ja, dafür gibt es gültige Verwendungen. Deshalb ist die API überhaupt vorhanden. Sie sind jedoch selten und weit voneinander entfernt. Nach meiner Erfahrung tun dies viele Menschen, weil sie nicht wirklich verstehen, wie ein Problem am besten gelöst werden kann, dh "Ich möchte den Code in meinem Ereignishandler für Schaltflächenklicks aufrufen, aber nicht nur, wenn auf eine Schaltfläche geklickt wird". Für einen Anfänger erscheint es daher logisch, einen Klick auf eine Schaltfläche zu simulieren. Wenn er diesen Code wirklich nehmen, in eine Funktion werfen und von einer anderen Stelle im Code aus aufrufen sollte.
Ed S.
6
@ Eds: Die Frage war ziemlich auf den Punkt. Ich hätte viel mehr Details zum Erstellen einer Tastatur hinzufügen können und trotzdem die gleiche Antwort erhalten. Wenn man bedenkt, dass ich genau das bekommen habe, was ich brauchte, scheint es mir keine Frage von "schlechter Qualität" zu sein.
Dan Vogel

Antworten:

147

Die Frage ist mit WPF gekennzeichnet, aber die bisherigen Antworten sind spezifische WinForms und Win32.

Erstellen Sie dazu in WPF einfach ein KeyEventArgs und rufen Sie RaiseEvent für das Ziel auf. So senden Sie beispielsweise ein KeyDown-Ereignis zum Einfügen eines Schlüssels an das aktuell fokussierte Element:

  var key = Key.Insert;                    // Key to send
  var target = Keyboard.FocusedElement;    // Target element
  var routedEvent = Keyboard.KeyDownEvent; // Event to send

  target.RaiseEvent(
    new KeyEventArgs(
      Keyboard.PrimaryDevice,
      PresentationSource.FromVisual(target),
      0,
      key)
    { RoutedEvent=routedEvent }
  );

Diese Lösung basiert nicht auf nativen Anrufen oder Windows-Interna und sollte viel zuverlässiger sein als die anderen. Außerdem können Sie einen Tastendruck auf ein bestimmtes Element simulieren.

Beachten Sie, dass dieser Code nur für PreviewKeyDown-, KeyDown-, PreviewKeyUp- und KeyUp-Ereignisse gilt. Wenn Sie TextInput-Ereignisse senden möchten, gehen Sie stattdessen folgendermaßen vor:

  var text = "Hello";
  var target = Keyboard.FocusedElement;
  var routedEvent = TextCompositionManager.TextInputEvent;

  target.RaiseEvent(
    new TextCompositionEventArgs(
      InputManager.Current.PrimaryKeyboardDevice,
      new TextComposition(InputManager.Current, target, text))
    { RoutedEvent = routedEvent }
  );

Beachten Sie auch Folgendes:

  • Steuerelemente erwarten Preview-Ereignisse, z. B. sollte PreviewKeyDown vor KeyDown stehen

  • Mit target.RaiseEvent (...) wird das Ereignis ohne Meta-Verarbeitung wie Beschleuniger, Textkomposition und IME direkt an das Ziel gesendet. Dies ist normalerweise das, was Sie wollen. Wenn Sie jedoch aus irgendeinem Grund wirklich tun, um die tatsächlichen Tastaturtasten zu simulieren, verwenden Sie stattdessen InputManager.ProcessInput ().

Ray Burns
quelle
1
Ich habe gerade Ihren Vorschlag ausprobiert, ich sehe keine Wirkung. Ich habe dem fokussierten Element einen keyDown-Ereignishandler hinzugefügt. Das Ereignis, das ich ausgelöst habe, wurde empfangen, aber der KeyState ist None, der ScanCode ist 0 und isDown ist false. Ich gehe davon aus, dass ich diese Werte erhalte, da dies der tatsächliche Status der Tastatur ist. Wenn Sie eine Taste auf der eigentlichen Tastatur drücken, ist KeyState = Down, isDown = true und ScanCode hat einen Wert.
Dan Vogel
24
Als ich den ersten Code von Keydown ausprobierte, bekam ich einen Fehler in "Ziel". Kann ihn nicht in ein visuelles konvertieren. Warum?
Kartal
3
Dan, weißt du, wie man das Drücken einer Taste mit einem Modifikator (Strg / Alt / Umschalt) emuliert? Insbesondere muss ich InputBinding simulieren: m_shell.InputBindings.Add (neues KeyBinding (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
Shrike
14
Über das Ziel Problem, arbeitete ich es heraus , indem Sie Keyboard.PrimaryDevice.ActiveSourcesiehe stackoverflow.com/questions/10820990/...
OscarRyz
4
Diese Antwort ist sehr gut, kann aber nicht zum Senden eines Schlüssels mit einem Modifikator verwendet werden, wie @Shrike feststellte. (ZB Ctrl+C)
ANeves
28

Um Schlüsselereignisse ohne Windows Forms-Kontext zu erzeugen, können Sie die folgende Methode verwenden:

[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

Beispielcode ist unten angegeben:

const int VK_UP = 0x26; //up key
const int VK_DOWN = 0x28;  //down key
const int VK_LEFT = 0x25;
const int VK_RIGHT = 0x27;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
int press()
{
    //Press the key
    keybd_event((byte)VK_UP, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
    return 0;
}

Liste der virtuellen Tasten definiert sind hier .

Um das vollständige Bild zu erhalten, verwenden Sie bitte den folgenden Link: http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html

Rajesh
quelle
Geeignet, wenn Ihr Fenster oben ist. Es hat meine Situation teilweise gelöst, danke!
Sergey
Eine Ergänzung zu Rajeshs Antwort: Wenn Sie dies auf einer mobilen Plattform tun möchten, müssen Sie "coredll.ddl" importieren
user1123236
22

Ich habe es nicht benutzt, aber SendKeys kann tun, was Sie wollen.

Verwenden Sie SendKeys, um Tastenanschläge und Tastenkombinationen an die aktive Anwendung zu senden. Diese Klasse kann nicht instanziiert werden. Verwenden Sie Senden, um einen Tastenanschlag an eine Klasse zu senden und sofort mit dem Ablauf Ihres Programms fortzufahren. Verwenden Sie SendWait, um auf Prozesse zu warten, die mit dem Tastenanschlag gestartet wurden.

System.Windows.Forms.SendKeys.Send("A");
System.Windows.Forms.SendKeys.Send("{ENTER}");

Microsoft hat einige weitere Beispiele für die Verwendung hier .

Michael Petrotta
quelle
3
Ich habe versucht, SendKeys.Send zu verwenden, und es wird folgende InvalidOperationException angezeigt: "SendKeys kann in dieser Anwendung nicht ausgeführt werden, da die Anwendung keine Windows-Nachrichten verarbeitet. Ändern Sie entweder die Anwendung, um Nachrichten zu verarbeiten, oder verwenden Sie die SendKeys.SendWait-Methode." Die Verwendung von SendKey.SendWait hat keine Auswirkung.
Dan Vogel
Stellen Sie sicher, dass Sie das Schlüsselereignis nicht an sich selbst senden. Schalten Sie den Fokus auf den richtigen Prozess, bevor Sie das Ereignis senden. Der zweite verlinkte Artikel hat einige Hilfe dazu.
Michael Petrotta
11

Leicht! (weil jemand anderes bereits die Arbeit für uns erledigt hat ...)

Nachdem ich viel Zeit damit verbracht hatte, dies mit den vorgeschlagenen Antworten zu versuchen, stieß ich auf dieses Codeplex-Projekt Windows Input Simulator, das es so einfach wie möglich machte, einen Tastendruck zu simulieren:

  1. Die Installation des Pakets kann über den NuGet-Paketmanager oder über die Paketmanagerkonsole erfolgen:

    Install-Package InputSimulator

  2. Verwenden Sie diese 2 Codezeilen:

    inputSimulator = new InputSimulator() inputSimulator.Keyboard.KeyDown(VirtualKeyCode.RETURN)

Und das ist es!

-------BEARBEITEN--------

Die Projektseite auf Codeplex ist aus irgendeinem Grund markiert. Dies ist der Link zur NuGet-Galerie.

Ravid Goldenberg
quelle
Dies funktioniert sehr gut, aber ich konnte nicht herausfinden, wie dies mit einer Kombination von Schlüsseln
funktioniert
Wenn Sie Tastenkombination sagen, meinen Sie damit STRG-C?
Ravid Goldenberg
Ja, oder selbst wenn Sie wollten, dass eine Konsolenanwendung im Vollbildmodus angezeigt wird, z. B. Alt-Enter, ich weiß, dass Sie F11 verwenden können, um den Vollbildmodus
aufzurufen,
1
Nun, Sie können das tun, obwohl ich es noch nicht ausprobiert habe. Verwenden Sie einfach inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C).
Ravid Goldenberg