Come posso generare programmaticamente eventi di pressione dei tasti in C #?


107

Come posso creare a livello di codice un evento che simuli la pressione di un tasto sulla tastiera?


6
Hai solo bisogno che l'evento si attivi?
Daniel A. White,

Penso che dovresti entrare nel codice non gestito per simulare una pressione di un tasto "reale".
Jonas B

Sì, ho solo bisogno che l'evento si attivi.
Dan Vogel,

1
@GONeale: Wow, un commento di tre anni. Va bene allora. Sì, ci sono usi validi per questo, ecco perché l'API esiste in primo luogo. Tuttavia sono pochi e lontani tra loro. Nella mia esperienza molte persone lo fanno perché non capiscono veramente il modo migliore per affrontare un problema, cioè, "Voglio chiamare il codice nel mio gestore di eventi di clic del pulsante, ma non solo quando viene cliccato un pulsante". Quindi, per un principiante, sembra logico simulare il clic di un pulsante, quando quello che dovrebbero fare è prendere quel codice, lanciarlo in una funzione e chiamarlo da un'altra parte del codice.
Ed S.

6
@EdS: La domanda era piuttosto pertinente. Avrei potuto aggiungere molti dettagli in eccesso sulla creazione di una tastiera e ottenere comunque la stessa risposta. Considerando che ho ottenuto esattamente ciò di cui avevo bisogno, non mi sembra una domanda di "scarsa qualità".
Dan Vogel

Risposte:


147

La domanda è contrassegnata come WPF ma le risposte finora sono WinForm e Win32 specifici.

Per eseguire questa operazione in WPF, è sufficiente creare un KeyEventArgs e chiamare RaiseEvent sulla destinazione. Ad esempio, per inviare un evento KeyDown della chiave di inserimento all'elemento attualmente attivo:

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 }
);

Questa soluzione non si basa su chiamate native o interni di Windows e dovrebbe essere molto più affidabile delle altre. Consente inoltre di simulare la pressione di un tasto su un elemento specifico.

Tieni presente che questo codice è applicabile solo agli eventi PreviewKeyDown, KeyDown, PreviewKeyUp e KeyUp. Se vuoi inviare eventi TextInput, dovrai farlo invece:

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 }
);

Notare inoltre che:

  • I controlli si aspettano di ricevere eventi di anteprima, ad esempio PreviewKeyDown dovrebbe precedere KeyDown

  • L'utilizzo di target.RaiseEvent (...) invia l'evento direttamente al target senza meta-elaborazione come acceleratori, composizione del testo e IME. Normalmente è quello che vuoi. D'altra parte, se si fa davvero cosa simulare i tasti della tastiera effettivi per qualche motivo, si utilizzerà invece InputManager.ProcessInput ().


1
Ho appena provato il tuo suggerimento, non vedo alcun effetto. Ho collegato un gestore di eventi keyDown all'elemento focalizzato. L'evento che ho generato viene ricevuto, ma KeyState è None, ScanCode è 0 e isDown è false. Presumo di ottenere questi valori perché questo è lo stato effettivo della tastiera. Premendo un tasto sulla tastiera effettiva, KeyState = Down, isDown = true e ScanCode ha un valore.
Dan Vogel,

25
quando ho provato il primo codice di keydown ho ricevuto un errore in "target" non posso convertirlo in visual perch?
kartal

3
Dan, sai come emulare la pressione di un tasto con un modificatore (ctrl / alt / shift)? In particolare ho bisogno di simulare InputBinding: m_shell.InputBindings.Add (new KeyBinding (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
Shrike

14
Per quanto riguarda il problema di destinazione , l'ho risolto utilizzando Keyboard.PrimaryDevice.ActiveSourcevedi stackoverflow.com/questions/10820990/…
OscarRyz

4
Questa risposta è molto buona, ma non può essere utilizzata per inviare una chiave con un modificatore, come ha notato @Shrike. (Es Ctrl+C.)
ANeves

27

Per produrre eventi chiave senza contesto Windows Form, possiamo utilizzare il seguente metodo,

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

il codice di esempio è fornito di seguito:

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

L'elenco delle chiavi virtuali è definito qui .

Per ottenere il quadro completo, utilizzare il collegamento sottostante, http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html


Adatto, se la tua finestra sarà in alto. Ha parzialmente risolto la mia situazione, grazie!
Sergey

In aggiunta alla risposta di Rajesh, se desideri eseguire questa operazione su una piattaforma mobile, devi importare "coredll.ddl"
user1123236

21

Non l'ho usato, ma SendKeys potrebbe fare quello che vuoi.

Utilizzare SendKeys per inviare sequenze di tasti e combinazioni di tasti all'applicazione attiva. Questa classe non può essere istanziata. Per inviare una sequenza di tasti a una classe e continuare immediatamente con il flusso del programma, utilizzare Invia. Per attendere eventuali processi avviati dalla sequenza di tasti, utilizzare SendWait.

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

Microsoft ha alcuni altri esempi di utilizzo qui .


3
Ho provato a utilizzare SendKeys.Send e ottengo questa InvalidOperationException: "SendKeys non può essere eseguito all'interno di questa applicazione perché l'applicazione non gestisce i messaggi di Windows. Modifica l'applicazione per gestire i messaggi o utilizza il metodo SendKeys.SendWait." L'utilizzo di SendKey.SendWait non ha alcun effetto.
Dan Vogel,

Assicurati di non inviare l'evento chiave a te stesso. Passa al processo corretto prima di inviare l'evento. Il secondo articolo collegato ha qualche aiuto su questo.
Michael Petrotta

11

Facilmente! (perché qualcun altro ha già fatto il lavoro per noi ...)

Dopo aver passato molto tempo a provare con le risposte suggerite, mi sono imbattuto in questo progetto codeplex Windows Input Simulator che ha reso semplice simulare la pressione di un tasto:

  1. Installare il pacchetto, può essere eseguito o dal gestore di pacchetti NuGet o dalla console del gestore di pacchetti come:

    Install-Package InputSimulator

  2. Usa queste 2 righe di codice:

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

E questo è tutto!

-------MODIFICARE--------

La pagina del progetto su codeplex è contrassegnata per qualche motivo, questo è il collegamento alla raccolta NuGet.


Funziona molto bene, tuttavia non sono riuscito a trovare come farlo funzionare con una combinazione di tasti,
user1234433222

Quando dici una combinazione di tasti, intendi come CTRL-C?
Ravid Goldenberg

sì o anche se si desidera che un'applicazione console vada a schermo intero, ad esempio Alt-Invio, so che è possibile utilizzare F11 per accedere a schermo intero ma sarebbe bello vedere se Alt-Invio funzionerebbe :)
user1234433222

1
Bene, puoi farlo, anche se non l'ho provato, usa semplicemente inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
Ravid Goldenberg

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.