Simulando eventos "keypress" de la manera correcta usando InputSimulator con C# en WinForms

Simulando eventos "keypress" de la manera correcta usando InputSimulator con C# en WinForms

Seguramente todos los desarrolladores de C# que trabajan con WinForms conocen el famoso snippet que te ayuda a simular la acción de una tecla:

// Importar la dll user32.dll
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo); 

// Declara algunos códigos de teclas como constantes con su respectivo código
// Conoce los códigos de teclas: https://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
public const int KEYEVENTF_EXTENDEDKEY = 0x0001; // al oprimir tecla
public const int KEYEVENTF_KEYUP = 0x0002; // al levantar tecla
public const int VK_RCONTROL = 0xA3; //Tecla CTRL derecha

// Simular evento keypress
keybd_event(VK_RCONTROL, 0, KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(VK_RCONTROL, 0, KEYEVENTF_KEYUP, 0); 

Sin embargo este código se puede volver un dolor de cabeza para mantener. Por ello, te mostraremos en este artículo la manera correcta, más fácil y funcional de simular eventos keypress de cualquier tecla del teclado usando la librería Input Simulator. Esta librería provee una sencilla interfaz de .NET escrita en C# que simula eventos tanto como para teclado así como para Mouse usando la api de Win32 SendInput. Toda la interoperación está ya hecha y existe incluso la funcionalidad de simular atajos de teclado tambien.

Ventajas de trabajar con InputSimulator

Windows Forms provee la api de SendKey que te ayuda a simular la entrada de texto, sin embargo no es posible simular atajos de teclado. Esta librería puede ser usada en WPF, Windows Forms y aplicaciones de Consola para sintetizar o simular cualquier evento de teclado incluyendo teclas especiales como Control, Alt, Shif, Tab, Enter, Tecla de Espacio, Windows, Caps Lock, Num Lock, Scroll Lock, Volumen y Mute, Web, Mail, Busqueda, Favoritos, Teclas de Funciones y otro tipos de teclas definidas en la tabla virtual de teclas.

Ancioso por probar la librería? Continua leyendo !

1. Instalar InputSimulator

Lo primero que necesitas hacer, es instalar la librería en tu proyecto usando nuGet. Abre tu proyecto de Winforms en C# y abre el manager de paquetes nuGet en el explorador de soluciones:

Ve a la ventana explorar y busca por InputSimulator:

InputSimulator nuget install

De la lista que se muestra, instala el paquete de Michael Noonan y procede con la instalación. Una vez la instalación de paquetes finaliza, podrás usarla en tus clases. Para más información acerca de esta librería y ejemplos, por favor visita el repositorio oficial en Github aquí.

2. Usando InputSimulator

Antes de usar Input Simulator necesitarás incluir los tipos requeridos al inicio de tus clases:

using WindowsInput.Native; 
using WindowsInput;

Lista de códigos de tecla virtuales

Si quieres simular teclas diferentes (o las mismas disponibles en la librería), necesitarás el código de tecla de cada una de ellas. Sin embargo puedes usar simplemente la interfaz enum de WindowsInput.Native.VirtualKeyCode que contiene una propiedad para cada tecla.

Simular Keypress

Para simular el evento de una tecla, usa el método Keyboard.KeyPress que espera el código de tecla virtual que quieres simular:

InputSimulator sim = new InputSimulator();

// Presionar tecla 0
sim.Keyboard.KeyPress(VirtualKeyCode.VK_0);
//  Presionar tecla 1
sim.Keyboard.KeyPress(VirtualKeyCode.VK_1);
//  Presionar tecla b
sim.Keyboard.KeyPress(VirtualKeyCode.VK_B);
//  Presionar tecla v
sim.Keyboard.KeyPress(VirtualKeyCode.VK_V);
//  Presionar tecla enter
sim.Keyboard.KeyPress(VirtualKeyCode.RETURN);
//  Presionar tecla CTRL izquierdo
sim.Keyboard.KeyPress(VirtualKeyCode.LCONTROL);

Como mencionamos, la lógica no está limitada solamente a eventos sencillos de keypress sino tambien a "KeyDown" y "KeyUp".

Simular Keystrokes

Si deseas simular atajos de teclados, puedes usar la funcion ModifiedKeyStroke del objeto Keyboard:

InputSimulator sim = new InputSimulator();

// CTRL + C (funciona como una función copiar texto en muchas situaciones)
sim.Keyboard.ModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.VK_C);

// Puedes simular multiples combinaciones con diferentes modificadores
// Por ejemplo CTRL + K + C que es simulado como 
// CTRL-down, K, C, CTRL-up
sim.Keyboard.ModifiedKeyStroke(VirtualKeyCode.CONTROL, new[] {
    VirtualKeyCode.VK_K, VirtualKeyCode.VK_C
});

// Puedes simular combinaciones complejas con diferentes modificadores
// Por ejemplo CTRL-ALT-SHIFT-ESC-K que es simulado como:
// CTRL + down, ALT + down, SHIFT + down, press ESC, press K, SHIFT-up, ALT-up, CTRL-up
sim.Keyboard.ModifiedKeyStroke(
    new[] { VirtualKeyCode.CONTROL, VirtualKeyCode.MENU, VirtualKeyCode.SHIFT },
    new[] { VirtualKeyCode.ESCAPE, VirtualKeyCode.VK_K }
);

Escribir palabras enteras

El método TextEntry del objeto Keyboard simula la inserción ininterrumpida de texto en el teclado:

InputSimulator Simulator = new InputSimulator();

Simulator.Keyboard.TextEntry("Hola Mundo!");

La api del simulador es encadenable, así que puedes usar el método Sleep para esperar cierta cantidad de milisegundo antes y despues de iniciar la escritura de algo:

InputSimulator Simulator = new InputSimulator();
            
// Esperar un segundo para comenzar a escribir
Simulator.Keyboard.Sleep(1000)
// Escribir Hola Mundo !
.TextEntry("Hola Mundo !")
// Esperar otro segundo
.Sleep(1000)
// Escribir más texto
.TextEntry("otro texto que quieras escribir")
;

Simular escritura de texto por caracteres

Si eres peresozo y quieres crear snippets de código para hacer tu vida más sencilla, lo más probable es que quieras crear una aplicación que simula la escritura de algo por ti. Obviamente el texto necesita existir, así que lo puedes usar por ejemplo durante la grabación de un video, donde es probable que no quieras cometer errores:

/// <summary>
/// Simular la escritura de cualquier texto como cuando escribes normalmente.
/// </summary>
/// <param name="Text">Texto que va a ser escrito automaticamente.</param>
/// <param name="typingDelay">Tiempo en ms a esperar despues de que 1 caracter es escrito.</param>
/// <param name="startDelay"></param>
private void simulateTypingText(string Text, int typingDelay = 100, int startDelay = 0)
{
    InputSimulator sim = new InputSimulator();

    // Esperar el tiempo inicial de espera
    sim.Keyboard.Sleep(startDelay);

    // Divide el texto en lineas en caso de que hayan
    string[] lines = Text.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None);

    // Algunas variables bandera para calcular el porcentaje de progreso de escritura
    int maximum = lines.Length;
    int current = 1;

    foreach (string line in lines)
    {
        // Divide la linea en caracteres
        char[] words = line.ToCharArray();

        // Simula la escritura del caracter i.e:  a, e , i ,o ,u etc
        // Aplica inmediatamente el tiempo de espera
        foreach (char word in words)
        {
            sim.Keyboard.TextEntry(word).Sleep(typingDelay);
        }

        float percentage = ((float)current / (float)maximum) * 100;

        current++;

        // Agrega una nueva linea presionando enter
        // Regresa al inicio de la linea en tu editor usando la tecla HOME
        sim.Keyboard.KeyPress(VirtualKeyCode.RETURN);
        sim.Keyboard.KeyPress(VirtualKeyCode.HOME);

        // Muestra el porcentaje en la consola
        Console.WriteLine("Porcentaje : {0}", percentage.ToString());
    }
}

El método espera como primer argumento el texto que será escrito como cualquier humano lo hará. El tiempo de espera por defecto despues de la escritura de cada caracter es de 100 milisegundos que es usualmente el tiempo en promedio que tarda una persona en promedio al oprimir en el teclado. El ultimo argumento es totalmente opcional y provee un tiempo de espera para iniciar la escritura del texto:

// Simular escritura de texto multilinea
simulateTypingText(textBox1.Text);

// Simular escritura lentamente esperando medio segundo despues de escribir cada caracter
simulateTypingText(textBox1.Text, 500);

// Simular escritura lentamente esperando medio segundo despues de escribir cada caracter
// y esperar 5 segundos antes de empezar
simulateTypingText(textBox1.Text, 500, 5000);

Que te diviertas !

Esto podría ser de tu interes

Conviertete en un programador más sociable