2012-10-06 18 views
16

Estoy usando this board como un teclado para propósitos de demostración.Enviar claves a través de SendInput en user32.dll

De todos modos, para resumir, todo funciona bien, salvo en muy pocos casos. Envío pulsaciones de teclas con la función SendInput ubicada en user32.dll.

Así que mi programa se parece a:

static void Main(string[] args) 
{ 
    Console.Write("Press enter an on the next secont the key combination shift+end will be send"); 
    Console.Read(); 

    Thread.Sleep(1000); 

    SendKeyDown(KeyCode.SHIFT); 
    SendKeyPress(KeyCode.END); 
    SendKeyUp(KeyCode.SHIFT); 

    Console.Read(); 
    Console.Read(); 
} 

[DllImport("user32.dll", SetLastError = true)] 
private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure); 

/// <summary> 
/// simulate key press 
/// </summary> 
/// <param name="keyCode"></param> 
public static void SendKeyPress(KeyCode keyCode) 
{ 
    INPUT input = new INPUT { 
     Type = 1 
    }; 
    input.Data.Keyboard = new KEYBDINPUT() { 
     Vk = (ushort)keyCode, 
     Scan = 0, 
     Flags = 0, 
     Time = 0, 
     ExtraInfo = IntPtr.Zero, 
    }; 

    INPUT input2 = new INPUT { 
     Type = 1 
    }; 
    input2.Data.Keyboard = new KEYBDINPUT() { 
     Vk = (ushort)keyCode, 
     Scan = 0, 
     Flags = 2, 
     Time = 0, 
     ExtraInfo = IntPtr.Zero 
    }; 
    INPUT[] inputs = new INPUT[] { input, input2 }; 
    if (SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))) == 0) 
     throw new Exception();    
} 

/// <summary> 
/// Send a key down and hold it down until sendkeyup method is called 
/// </summary> 
/// <param name="keyCode"></param> 
public static void SendKeyDown(KeyCode keyCode) 
{ 
    INPUT input = new INPUT{ 
     Type = 1 
    }; 
    input.Data.Keyboard = new KEYBDINPUT(); 
    input.Data.Keyboard.Vk = (ushort)keyCode; 
    input.Data.Keyboard.Scan = 0; 
    input.Data.Keyboard.Flags = 0; 
    input.Data.Keyboard.Time = 0; 
    input.Data.Keyboard.ExtraInfo = IntPtr.Zero; 
    INPUT[] inputs = new INPUT[] { input }; 
    if (SendInput(1, inputs, Marshal.SizeOf(typeof(INPUT))) == 0) 
    { 
     throw new Exception(); 
    } 
} 

/// <summary> 
/// Release a key that is being hold down 
/// </summary> 
/// <param name="keyCode"></param> 
public static void SendKeyUp(KeyCode keyCode) 
{ 
    INPUT input = new INPUT { 
     Type = 1 
    }; 
    input.Data.Keyboard = new KEYBDINPUT(); 
    input.Data.Keyboard.Vk = (ushort)keyCode; 
    input.Data.Keyboard.Scan = 0; 
    input.Data.Keyboard.Flags = 2; 
    input.Data.Keyboard.Time = 0; 
    input.Data.Keyboard.ExtraInfo = IntPtr.Zero; 
    INPUT[] inputs = new INPUT[] { input }; 
    if (SendInput(1, inputs, Marshal.SizeOf(typeof(INPUT))) == 0) 
     throw new Exception(); 

} 

Y aquí están las estructuras que he encontrado en línea que esos métodos utilizan y también los códigos clave: (tenga en cuenta que se parece a una gran cantidad de código y es porque hay son un montón de códigos de teclas en un Enum)

/// <summary> 
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646270(v=vs.85).aspx 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential)] 
    internal struct INPUT 
    { 
     public uint Type; 
     public MOUSEKEYBDHARDWAREINPUT Data; 
    } 

    /// <summary> 
    /// http://social.msdn.microsoft.com/Forums/en/csharplanguage/thread/f0e82d6e-4999-4d22-b3d3-32b25f61fb2a 
    /// </summary> 
    [StructLayout(LayoutKind.Explicit)] 
    internal struct MOUSEKEYBDHARDWAREINPUT 
    { 
     [FieldOffset(0)] 
     public HARDWAREINPUT Hardware; 
     [FieldOffset(0)] 
     public KEYBDINPUT Keyboard; 
     [FieldOffset(0)] 
     public MOUSEINPUT Mouse; 
    } 

    /// <summary> 
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential)] 
    internal struct HARDWAREINPUT 
    { 
     public uint Msg; 
     public ushort ParamL; 
     public ushort ParamH; 
    } 

    /// <summary> 
    /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential)] 
    internal struct KEYBDINPUT 
    { 
     public ushort Vk; 
     public ushort Scan; 
     public uint Flags; 
     public uint Time; 
     public IntPtr ExtraInfo; 
    } 

    /// <summary> 
    /// http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/2abc6be8-c593-4686-93d2-89785232dacd 
    /// </summary> 
    [StructLayout(LayoutKind.Sequential)] 
    internal struct MOUSEINPUT 
    { 
     public int X; 
     public int Y; 
     public uint MouseData; 
     public uint Flags; 
     public uint Time; 
     public IntPtr ExtraInfo; 
    } 

    public enum KeyCode : ushort 
    { 
     #region Media 

     /// <summary> 
     /// Next track if a song is playing 
     /// </summary> 
     MEDIA_NEXT_TRACK = 0xb0, 

     /// <summary> 
     /// Play pause 
     /// </summary> 
     MEDIA_PLAY_PAUSE = 0xb3, 

     /// <summary> 
     /// Previous track 
     /// </summary> 
     MEDIA_PREV_TRACK = 0xb1, 

     /// <summary> 
     /// Stop 
     /// </summary> 
     MEDIA_STOP = 0xb2, 

     #endregion 

     #region math 

     /// <summary>Key "+"</summary> 
     ADD = 0x6b, 
     /// <summary> 
     /// "*" key 
     /// </summary> 
     MULTIPLY = 0x6a, 

     /// <summary> 
     /// "/" key 
     /// </summary> 
     DIVIDE = 0x6f, 

     /// <summary> 
     /// Subtract key "-" 
     /// </summary> 
     SUBTRACT = 0x6d, 

     #endregion 

     #region Browser 
     /// <summary> 
     /// Go Back 
     /// </summary> 
     BROWSER_BACK = 0xa6, 
     /// <summary> 
     /// Favorites 
     /// </summary> 
     BROWSER_FAVORITES = 0xab, 
     /// <summary> 
     /// Forward 
     /// </summary> 
     BROWSER_FORWARD = 0xa7, 
     /// <summary> 
     /// Home 
     /// </summary> 
     BROWSER_HOME = 0xac, 
     /// <summary> 
     /// Refresh 
     /// </summary> 
     BROWSER_REFRESH = 0xa8, 
     /// <summary> 
     /// browser search 
     /// </summary> 
     BROWSER_SEARCH = 170, 
     /// <summary> 
     /// Stop 
     /// </summary> 
     BROWSER_STOP = 0xa9, 
     #endregion 

     #region Numpad numbers 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD0 = 0x60, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD1 = 0x61, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD2 = 0x62, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD3 = 0x63, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD4 = 100, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD5 = 0x65, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD6 = 0x66, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD7 = 0x67, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD8 = 0x68, 
     /// <summary> 
     /// 
     /// </summary> 
     NUMPAD9 = 0x69, 

     #endregion 

     #region Fkeys 
     /// <summary> 
     /// F1 
     /// </summary> 
     F1 = 0x70, 
     /// <summary> 
     /// F10 
     /// </summary> 
     F10 = 0x79, 
     /// <summary> 
     /// 
     /// </summary> 
     F11 = 0x7a, 
     /// <summary> 
     /// 
     /// </summary> 
     F12 = 0x7b, 
     /// <summary> 
     /// 
     /// </summary> 
     F13 = 0x7c, 
     /// <summary> 
     /// 
     /// </summary> 
     F14 = 0x7d, 
     /// <summary> 
     /// 
     /// </summary> 
     F15 = 0x7e, 
     /// <summary> 
     /// 
     /// </summary> 
     F16 = 0x7f, 
     /// <summary> 
     /// 
     /// </summary> 
     F17 = 0x80, 
     /// <summary> 
     /// 
     /// </summary> 
     F18 = 0x81, 
     /// <summary> 
     /// 
     /// </summary> 
     F19 = 130, 
     /// <summary> 
     /// 
     /// </summary> 
     F2 = 0x71, 
     /// <summary> 
     /// 
     /// </summary> 
     F20 = 0x83, 
     /// <summary> 
     /// 
     /// </summary> 
     F21 = 0x84, 
     /// <summary> 
     /// 
     /// </summary> 
     F22 = 0x85, 
     /// <summary> 
     /// 
     /// </summary> 
     F23 = 0x86, 
     /// <summary> 
     /// 
     /// </summary> 
     F24 = 0x87, 
     /// <summary> 
     /// 
     /// </summary> 
     F3 = 0x72, 
     /// <summary> 
     /// 
     /// </summary> 
     F4 = 0x73, 
     /// <summary> 
     /// 
     /// </summary> 
     F5 = 0x74, 
     /// <summary> 
     /// 
     /// </summary> 
     F6 = 0x75, 
     /// <summary> 
     /// 
     /// </summary> 
     F7 = 0x76, 
     /// <summary> 
     /// 
     /// </summary> 
     F8 = 0x77, 
     /// <summary> 
     /// 
     /// </summary> 
     F9 = 120, 

     #endregion 

     #region Other 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_1 = 0xba, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_102 = 0xe2, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_2 = 0xbf, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_3 = 0xc0, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_4 = 0xdb, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_5 = 220, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_6 = 0xdd, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_7 = 0xde, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_8 = 0xdf, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_CLEAR = 0xfe, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_COMMA = 0xbc, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_MINUS = 0xbd, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_PERIOD = 190, 
     /// <summary> 
     /// 
     /// </summary> 
     OEM_PLUS = 0xbb, 

     #endregion 

     #region KEYS 

     /// <summary> 
     /// 
     /// </summary> 
     KEY_0 = 0x30, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_1 = 0x31, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_2 = 50, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_3 = 0x33, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_4 = 0x34, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_5 = 0x35, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_6 = 0x36, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_7 = 0x37, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_8 = 0x38, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_9 = 0x39, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_A = 0x41, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_B = 0x42, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_C = 0x43, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_D = 0x44, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_E = 0x45, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_F = 70, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_G = 0x47, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_H = 0x48, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_I = 0x49, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_J = 0x4a, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_K = 0x4b, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_L = 0x4c, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_M = 0x4d, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_N = 0x4e, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_O = 0x4f, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_P = 80, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_Q = 0x51, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_R = 0x52, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_S = 0x53, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_T = 0x54, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_U = 0x55, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_V = 0x56, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_W = 0x57, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_X = 0x58, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_Y = 0x59, 
     /// <summary> 
     /// 
     /// </summary> 
     KEY_Z = 90, 

     #endregion 

     #region volume 
     /// <summary> 
     /// Decrese volume 
     /// </summary> 
     VOLUME_DOWN = 0xae, 

     /// <summary> 
     /// Mute volume 
     /// </summary> 
     VOLUME_MUTE = 0xad, 

     /// <summary> 
     /// Increase volue 
     /// </summary> 
     VOLUME_UP = 0xaf, 

     #endregion 


     /// <summary> 
     /// Take snapshot of the screen and place it on the clipboard 
     /// </summary> 
     SNAPSHOT = 0x2c, 

     /// <summary>Send right click from keyboard "key that is 2 keys to the right of space bar"</summary> 
     RightClick = 0x5d, 

     /// <summary> 
     /// Go Back or delete 
     /// </summary> 
     BACKSPACE = 8, 

     /// <summary> 
     /// Control + Break "When debuging if you step into an infinite loop this will stop debug" 
     /// </summary> 
     CANCEL = 3, 
     /// <summary> 
     /// Caps lock key to send cappital letters 
     /// </summary> 
     CAPS_LOCK = 20, 
     /// <summary> 
     /// Ctlr key 
     /// </summary> 
     CONTROL = 0x11, 

     /// <summary> 
     /// Alt key 
     /// </summary> 
     ALT = 18, 

     /// <summary> 
     /// "." key 
     /// </summary> 
     DECIMAL = 110, 

     /// <summary> 
     /// Delete Key 
     /// </summary> 
     DELETE = 0x2e, 


     /// <summary> 
     /// Arrow down key 
     /// </summary> 
     DOWN = 40, 

     /// <summary> 
     /// End key 
     /// </summary> 
     END = 0x23, 

     /// <summary> 
     /// Escape key 
     /// </summary> 
     ESC = 0x1b, 

     /// <summary> 
     /// Home key 
     /// </summary> 
     HOME = 0x24, 

     /// <summary> 
     /// Insert key 
     /// </summary> 
     INSERT = 0x2d, 

     /// <summary> 
     /// Open my computer 
     /// </summary> 
     LAUNCH_APP1 = 0xb6, 
     /// <summary> 
     /// Open calculator 
     /// </summary> 
     LAUNCH_APP2 = 0xb7, 

     /// <summary> 
     /// Open default email in my case outlook 
     /// </summary> 
     LAUNCH_MAIL = 180, 

     /// <summary> 
     /// Opend default media player (itunes, winmediaplayer, etc) 
     /// </summary> 
     LAUNCH_MEDIA_SELECT = 0xb5, 

     /// <summary> 
     /// Left control 
     /// </summary> 
     LCONTROL = 0xa2, 

     /// <summary> 
     /// Left arrow 
     /// </summary> 
     LEFT = 0x25, 

     /// <summary> 
     /// Left shift 
     /// </summary> 
     LSHIFT = 160, 

     /// <summary> 
     /// left windows key 
     /// </summary> 
     LWIN = 0x5b, 


     /// <summary> 
     /// Next "page down" 
     /// </summary> 
     PAGEDOWN = 0x22, 

     /// <summary> 
     /// Num lock to enable typing numbers 
     /// </summary> 
     NUMLOCK = 0x90, 

     /// <summary> 
     /// Page up key 
     /// </summary> 
     PAGE_UP = 0x21, 

     /// <summary> 
     /// Right control 
     /// </summary> 
     RCONTROL = 0xa3, 

     /// <summary> 
     /// Return key 
     /// </summary> 
     ENTER = 13, 

     /// <summary> 
     /// Right arrow key 
     /// </summary> 
     RIGHT = 0x27, 

     /// <summary> 
     /// Right shift 
     /// </summary> 
     RSHIFT = 0xa1, 

     /// <summary> 
     /// Right windows key 
     /// </summary> 
     RWIN = 0x5c, 

     /// <summary> 
     /// Shift key 
     /// </summary> 
     SHIFT = 0x10, 

     /// <summary> 
     /// Space back key 
     /// </summary> 
     SPACE_BAR = 0x20, 

     /// <summary> 
     /// Tab key 
     /// </summary> 
     TAB = 9, 

     /// <summary> 
     /// Up arrow key 
     /// </summary> 
     UP = 0x26, 

    } 

Así que ahora mi pregunta es ¿por qué cuando envío combinación de teclas que no consigo los mismos resultados que cuando lo haga en una verdadera ke ¿Yboard? 98% de las cosas funcionan. Por ejemplo, yo soy capaz de hacer:

SendKeyDown(KeyCode.SHIFT); 
    SendKeyPress(KeyCode.KEY_A); 
    SendKeyUp(KeyCode.SHIFT); 

y que va a enviar una mayúscula

¿Debo usar una biblioteca diferente?

La razón por la que me gusta este enfoque es que no sé de antemano si el usuario enviará una combinación de teclas Por ejemplo, en formas de las ventanas Si hago:

System.Windows.Forms.SendKeys.SendWait("+{end}"); que enviará shift + fin, sino tal vez el usuario solo desea enviar un cambio ...

Respuesta

10

No está configurando los indicadores y escaneando campos, dependiendo de las teclas que desee, deberá configurarlos correctamente para que el sistema operativo reconozca las claves correctamente.

Puede considerar el uso de la biblioteca Input Simulator, ya que ya hace lo que quiere y no tiene que volver a crear la rueda. Solo asegúrate de mirar a través de los foros ya que hay algunos parches buenos que deben establecerse, ya que el autor abandonó el proyecto en 2009. Sin embargo, es una buena biblioteca.

+1

GRACIAS esta es lo que he estado buscando! – hurnhu

0

Otra forma de enviar la entrada de teclado a una ventana (lo uso para las pruebas de interfaz de usuario) es utilizar la alternativa de Unicode en KEYBDINPUT que se salva de la cartografía de cada personaje a la tecla virtual:

public static void SendString(string inputStr) 
{ 
    var hWnd = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; 
    WinAPI.SetForegroundWindow(hWnd);   
    List<WinAPI.INPUT> keyList = new List<WinAPI.INPUT>(); 
    foreach (short c in inputStr) 
    { 
     switch (c) 
     { 
      case 8: // Translate \t to VK_TAB 
       { 
        WinAPI.INPUT keyDown = new WinAPI.INPUT(); 
        keyDown.type = 1; //Keyboard 
        keyDown.union.keyboardInput.wVk = (short)WinAPI.WindowsVirtualKey.VK_TAB; 
        keyDown.union.keyboardInput.dwFlags = 0; 
        keyDown.union.keyboardInput.wScan = 0; //use VirtualKey 
        keyList.Add(keyDown); 
        WinAPI.INPUT keyUp = new WinAPI.INPUT(); 
        keyUp.type = 1; //Keyboard 
        keyUp.union.keyboardInput.wVk = (short)WinAPI.WindowsVirtualKey.VK_TAB; 
        keyUp.union.keyboardInput.dwFlags = 0x0002; 
        keyUp.union.keyboardInput.wScan = 0; //use VirtualKey 
        keyList.Add(keyUp); 
       } 
       break; 
      case 10: // Translate \n to VK_RETURN 
       { 
        WinAPI.INPUT keyDown = new WinAPI.INPUT(); 
        keyDown.type = 1; //Keyboard 
        keyDown.union.keyboardInput.wVk = (short)WinAPI.WindowsVirtualKey.VK_RETURN; 
        keyDown.union.keyboardInput.dwFlags = 0; 
        keyDown.union.keyboardInput.wScan = 0; //use VirtualKey 
        keyList.Add(keyDown); 
        WinAPI.INPUT keyUp = new WinAPI.INPUT(); 
        keyUp.type = 1; //Keyboard 
        keyUp.union.keyboardInput.wVk = (short)WinAPI.WindowsVirtualKey.VK_RETURN; 
        keyUp.union.keyboardInput.dwFlags = 0x0002; 
        keyUp.union.keyboardInput.wScan = 0; //use VirtualKey 
        keyList.Add(keyUp); 
       } 
       break;     
      default: 
       { 
        WinAPI.INPUT keyDown = new WinAPI.INPUT(); 
        keyDown.type = 1; //Keyboard 
        keyDown.union.keyboardInput.wVk = 0; //Use unicode 
        keyDown.union.keyboardInput.dwFlags = 0x0004; //Unicode Key Down 
        keyDown.union.keyboardInput.wScan = c; 
        keyList.Add(keyDown); 
        WinAPI.INPUT keyUp = new WinAPI.INPUT(); 
        keyUp.type = 1; //Keyboard 
        keyUp.union.keyboardInput.wVk = 0; //Use unicode 
        keyUp.union.keyboardInput.dwFlags = 0x0004 | 0x0002; //Unicode Key Up 
        keyUp.union.keyboardInput.wScan = c; 
        keyList.Add(keyUp); 
       } 
       break; 
     } 
    } 
    WinAPI.SendInput((uint)keyList.Count, keyList.ToArray(), Marshal.SizeOf(typeof(WinAPI.INPUT)));    
} 
Cuestiones relacionadas