2012-10-06 46 views
16

Tôi đang sử dụng this board làm bàn phím cho mục đích demo.Gửi các khóa thông qua SendInput trong user32.dll

Dù sao để làm cho câu chuyện dài ngắn mọi thứ hoạt động tốt, ngoại trừ rất ít trường hợp. Tôi gửi các lần nhấn phím bằng chức năng SendInput nằm trong user32.dll.

Vì vậy, chương trình của tôi trông giống như:

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

} 

Và đây là các cấu trúc mà tôi tìm thấy trên mạng rằng những phương pháp sử dụng và cũng là mã chủ chốt: (lưu ý nó trông giống như rất nhiều mã và là bởi vì có rất nhiều mã chủ chốt trong một 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, 

    } 

vì vậy, bây giờ câu hỏi của tôi là tại sao khi tôi gửi mà tổ hợp phím tôi không nhận được kết quả tương tự như khi tôi làm điều đó trên một ke thực yboard? 98% số công việc. Ví dụ tôi có thể làm:

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

Và đó sẽ gửi một vốn A.

Tôi có nên sử dụng một thư viện khác nhau?

Lý do tại sao tôi thích phương pháp này là bởi vì tôi không biết trước nếu người dùng sẽ gửi một tổ hợp phím Ví dụ trong cửa sổ hình thức Nếu tôi làm:

System.Windows.Forms.SendKeys.SendWait("+{end}"); rằng sẽ gửi shift + end nhưng có thể người dùng chỉ muốn gửi thay đổi ...

Trả lời

10

Bạn không đặt cờ và trường quét, tùy thuộc vào tổ hợp phím mong muốn, bạn sẽ cần đặt chính xác các phím này để hệ điều hành nhận dạng khóa chính xác.

Bạn có thể xem xét sử dụng thư viện Input Simulator, vì nó đã làm những gì bạn muốn và bạn không phải tạo lại bánh xe. Chỉ cần chắc chắn để xem xét thông qua các diễn đàn như có một số bản vá lỗi tốt trong đó cần phải được thiết lập, kể từ khi tác giả bị bỏ rơi dự án trong năm 2009. Đó là một thư viện tốt dù sao.

+1

THANK YOU này là những gì tôi đang tìm kiếm! – hurnhu

0

Một cách khác để gửi đầu vào bàn phím để một cửa sổ (tôi sử dụng này để thử nghiệm giao diện người dùng) là sử dụng thay thế Unicode trong KEYBDINPUT đó giúp bạn tiết kiệm từ việc lập bản đồ từng nhân vật để phím ảo:

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)));    
} 
Các vấn đề liên quan