2012-10-06 37 views
16

我使用this board作为演示目的的键盘。通过user32.dll中的SendInput发送密钥

无论如何,使长话短说一切正常,除了极少数情况下。我发送位于user32.dll中的功能SendInput函数的击键。

所以我的计划是这样的:

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

} 

这里是我在网上找到,这些方法使用的结构,也是关键代码:(请注意,它看起来像一个大量的代码,是因为有在枚举了大量的关键代码)

/// <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, 

    } 

所以现在我的问题是为什么当我发送组合键我没有得到相同的结果,当我做一个真正的科yboard? 98%的工作。例如,我能够做到:

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

这将发出一个资本A.

我应该使用不同的图书馆吗?

为什么我喜欢这种方法的原因是因为我不是事先知道,如果用户将发出一个组合键例如在Windows窗体如果我做的更多信息:

System.Windows.Forms.SendKeys.SendWait("+{end}");将发送SHIFT + END但也许用户只是想要发送移位...

回答

10

根据所需的按键,您不设置标志和扫描字段,您需要正确设置这些以使操作系统正确识别键。

你可能会考虑使用Input Simulator库,因为它已经做了你想做的事情,你不必重新创建轮子。只要确保浏览论坛,因为作者在2009年放弃了该项目,所以需要设置一些好的补丁。尽管如此,它仍然是一个很好的图书馆。

+1

谢谢这是我一直在寻找的! – hurnhu

0

发送键盘输入到一个窗口(I用这个UI测试)的另一种方法是使用Unicode替代在KEYBDINPUT这样可以节省从每个字符映射为虚拟键:

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