Send keys through SendInput in user32.dll

前端 未结 3 948
执笔经年
执笔经年 2020-11-27 13:43

I am using this board as a keyboard for demo purposes.

Anyways to make the long story short everything works fine except for very few cases. I send keystrokes with th

相关标签:
3条回答
  • 2020-11-27 13:54

    You aren't setting the flags and scan fields, depending on the keystrokes desired, you will need to set these correctly to get the OS to recognize the keys correctly.

    You might consider using the Input Simulator library, since it already does what you want and you don't have to recreate the wheel. Just make sure to look through the forums as there are some good patches in there that need to be set, since the author abandoned the project in 2009. It's a good library nonetheless.

    0 讨论(0)
  • 2020-11-27 13:56

    Another way of sending keyboard input to a window (I use this for UI testing) is to use the Unicode alternative in KEYBDINPUT which saves you from mapping each character to the virtual key:

    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)));             
    }
    
    0 讨论(0)
  • 2020-11-27 14:09

    You could try this. It works for : Shift + A, Ctrl + LShiftv + S, Ctrl + A

    The others I didn't try but I think you could send any key combination

    public static void MultiKeyPress(KeyCode[] keys){
        INPUT[] inputs = new INPUT[keys.Count() * 2];
        for(int a = 0; a < keys.Count(); ++a){
            for(int b = 0; b < 2; ++b){
                inputs[(b == 0) ? a : inputs.Count() - 1 - a].Type = 1;
                inputs[(b == 0) ? a : inputs.Count() - 1 - a].Data.Keyboard = new KEYBDINPUT() {
                    Vk = (ushort)keys[a],
                    Scan = 0,
                    Flags = Convert.ToUInt32((b == 0)?0:2),
                    Time = 0,
                    ExtraInfo = IntPtr.Zero,
                };
            }
        }
        if (SendInput(Convert.ToUInt32(inputs.Count()), inputs, Marshal.SizeOf(typeof(INPUT))) == 0)
            throw new Exception();
    }
    
    //call with this :
    MultiKeyPress(new virtualInputs.KeyCode[] { KeyCode.LSHIFT, KeyCode.KEY_A });
    

    /!\ the window that have the focus will get the keypress so you need to make sure the right window have the focus

    0 讨论(0)
提交回复
热议问题