¿Cómo puedo generar eventos de pulsación de teclas mediante programación en C #?

107

¿Cómo puedo crear mediante programación un evento que simule una tecla presionada en el teclado?

Dan Vogel
fuente
6
¿Solo necesitas que el evento se dispare?
Daniel A. White
Creo que tendrías que ingresar al código no administrado para simular una pulsación de tecla "real".
Jonas B
Sí, solo necesito que se active el evento.
Dan Vogel
1
@GONeale: Vaya, un comentario de tres años. OK entonces. Sí, hay usos válidos para esto, es por eso que la API existe en primer lugar. Sin embargo, son pocos y distantes entre sí. En mi experiencia, muchas personas hacen esto porque realmente no entienden la mejor manera de abordar un problema, es decir, "Quiero llamar al código en mi controlador de eventos de clic de botón, pero no solo cuando se hace clic en un botón". Entonces, para un principiante, parece lógico simular un clic en un botón, cuando lo que realmente deberían hacer es tomar ese código, lanzarlo a una función y llamarlo desde otra parte del código.
Ed S.
6
@EdS: La pregunta va bastante al grano. Podría haber agregado muchos detalles en exceso sobre la creación de un teclado y aún así obtuve la misma respuesta. Considerando que obtuve exactamente lo que necesitaba, no me parece una pregunta de "mala calidad".
Dan Vogel

Respuestas:

147

La pregunta está etiquetada como WPF, pero las respuestas hasta ahora son específicas de WinForms y Win32.

Para hacer esto en WPF, simplemente construya un KeyEventArgs y llame a RaiseEvent en el destino. Por ejemplo, para enviar un evento Insertar clave KeyDown al elemento actualmente enfocado:

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

Esta solución no se basa en llamadas nativas o internos de Windows y debería ser mucho más confiable que las demás. También le permite simular una pulsación de tecla en un elemento específico.

Tenga en cuenta que este código solo se aplica a los eventos PreviewKeyDown, KeyDown, PreviewKeyUp y KeyUp. Si desea enviar eventos TextInput, hará esto en su lugar:

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

También tenga en cuenta que:

  • Los controles esperan recibir eventos de vista previa, por ejemplo, PreviewKeyDown debe preceder a KeyDown

  • El uso de target.RaiseEvent (...) envía el evento directamente al destino sin metaprocesamiento como aceleradores, composición de texto e IME. Esto es normalmente lo que quieres. Por otro lado, si realmente hace qué simular las teclas del teclado reales por alguna razón, usaría InputManager.ProcessInput () en su lugar.

Ray Burns
fuente
1
Acabo de probar tu sugerencia, no veo ningún efecto. Adjunté un controlador de eventos keyDown al elemento enfocado. Se recibe el evento que he generado, pero KeyState es None, ScanCode es 0 y isDown es falso. Supongo que obtengo estos valores porque este es el estado real del teclado. Al presionar una tecla en el teclado real, KeyState = Down, isDown = true y ScanCode tiene un valor.
Dan Vogel
25
cuando probé el primer código de keydown, obtuve un error en "target".
kartal
3
Dan, ¿sabes cómo emular presionar una tecla con un modificador (ctrl / alt / shift)? En particular, necesito simular InputBinding: m_shell.InputBindings.Add (new KeyBinding (m_command, Key.Insert, ModifierKeys.Control | ModifierKeys.Alt));
Shrike
14
Sobre el problema del objetivo , lo Keyboard.PrimaryDevice.ActiveSource
resolví
4
Esta respuesta es muy buena, pero no se puede usar para enviar una clave con un modificador, como señaló @Shrike. (Ej Ctrl+C.)
ANeves
27

Para producir eventos clave sin el contexto de Windows Forms, podemos usar el siguiente método,

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

el código de muestra se da a continuación:

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

La lista de claves virtuales se define aquí .

Para obtener la imagen completa, utilice el siguiente enlace, http://tksinghal.blogspot.in/2011/04/how-to-press-and-hold-keyboard-key.html

Rajesh
fuente
Adecuado, si su ventana estará en la parte superior. Resolvió parcialmente mi situación, ¡gracias!
Sergey
Una adición a la respuesta de Rajesh, si desea hacer esto en la plataforma móvil, debe importar "coredll.ddl"
user1123236
21

No lo he usado, pero SendKeys puede hacer lo que quieras.

Utilice SendKeys para enviar combinaciones de teclas y combinaciones de teclas a la aplicación activa. No se puede crear una instancia de esta clase. Para enviar una pulsación de tecla a una clase y continuar inmediatamente con el flujo de su programa, use Enviar. Para esperar cualquier proceso iniciado por la pulsación de tecla, use SendWait.

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

Microsoft tiene más ejemplos de uso aquí .

Michael Petrotta
fuente
3
Intenté usar SendKeys.Send y obtengo esta InvalidOperationException: "SendKeys no se puede ejecutar dentro de esta aplicación porque la aplicación no maneja mensajes de Windows. Cambie la aplicación para manejar mensajes o use el método SendKeys.SendWait". El uso de SendKey.SendWait no tiene ningún efecto.
Dan Vogel
Asegúrate de no enviarte el evento clave a ti mismo. Cambie el enfoque al proceso adecuado antes de enviar el evento. El segundo artículo vinculado tiene algo de ayuda al respecto.
Michael Petrotta
11

¡Fácilmente! (porque alguien más ya hizo el trabajo por nosotros ...)

Después de pasar mucho tiempo intentando esto con las respuestas sugeridas, me encontré con este proyecto de codeplex Windows Input Simulator que simplificó al máximo la simulación de presionar una tecla:

  1. Instale el paquete, se puede hacer o desde el administrador de paquetes NuGet o desde la consola del administrador de paquetes como:

    Install-Package InputSimulator

  2. Utilice estas 2 líneas de código:

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

¡Y eso es!

-------EDITAR--------

La página del proyecto en codeplex está marcada por algún motivo, este es el enlace a la galería de NuGet.

Ravid Goldenberg
fuente
Esto funciona muy bien, sin embargo, no he podido encontrar cómo hacer que esto funcione con una combinación de teclas,
user1234433222
Cuando dices combinación de teclas, ¿te refieres a CTRL-C?
Ravid Goldenberg
sí, o incluso si quisiera que una aplicación de consola vaya a pantalla completa, por ejemplo, Alt-Enter, sé que puede usar F11 para ingresar a pantalla completa, pero sería bueno ver si Alt-Enter funcionaría :)
user1234433222
1
Bueno, puedes hacer eso, aunque no lo he probado, solo usa inputSimulator.Keyboard.ModifiedKeyStroke (VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);
Ravid Goldenberg