使用SendInput自动化按键

时间:2014-04-21 18:58:43

标签: c# winapi sendinput

当我尝试使用SendInput发送单键按键和组合按键时,我无法让我的程序按住键盘按钮直到命令被释放。通过下面的代码,我可以通过首先点击 shift 来发送字符'a''A'。但是,我无法永久地按住'a'按钮。

public static void KeyDown()
{
    SwitchWindow(Process.GetProcessesByName("notepad").FirstOrDefault().MainWindowHandle);
    INPUT[] inputs = new INPUT[1];
    KEYBDINPUT kb = new KEYBDINPUT();

    //Set up generic keyboard event
    inputs[0].type = INPUT_KEYBOARD;
    kb.wScan = 0; // hardware scan code for key
    kb.time = 0;
    kb.dwExtraInfo = IntPtr.Zero;

    kb.dwFlags = 0; // 0 for key press

    //Press shift
    kb.wVk = (ushort)KeyCode.SHIFT;
    inputs[0].ki = kb;
    SendInput(1, inputs, Marshal.SizeOf(inputs[0]));

    //Press 'a' key
    kb.wVk = (ushort)0x41; // virtual-key code for the "a" key
    inputs[0].ki = kb;
    SendInput(1, inputs, Marshal.SizeOf(inputs[0]));

    //Release 'a' key
    kb.dwFlags = KEYEVENTF_KEYUP;
    kb.wVk = (ushort)0x41; // virtual-key code for the "a" key
    inputs[0].ki = kb;
    SendInput(1, inputs, Marshal.SizeOf(inputs[0]));

    //Release 'shift' key
    kb.dwFlags = KEYEVENTF_KEYUP;
    kb.wVk = (ushort)KeyCode.SHIFT; // virtual-key code for the "a" key
    inputs[0].ki = kb;
    SendInput(1, inputs, Marshal.SizeOf(inputs[0]));
}

任何想法,如果我删除最后两个SendInput,它不会只是暂停'A'

1 个答案:

答案 0 :(得分:1)

为了其他正在搜索如何在C#中使用SendInput()的人的利益,请参阅以下说明。

1)有两种方法可以使用SendInput()发送击键,使用扫描码或virtual-key code

2)如果您打算将键击发送到从Direct 3D(或其他DirectInput环境)获取输入的游戏或其他应用程序,则需要将键击作为扫描码发送,因此您指定了wScan字段,并离开wvk空白。请参阅此处的信息:KEYBDINPUT

3)在发送击键之前,请记住将焦点窗口切换到要发送击键的应用程序。例如:

MemoryHandler.SwitchWindow(Process.GetProcessesByName("notepad").FirstOrDefault().MainWindowHandle);

4)最终代码:

    public static void PressKey(char ch, bool press)
    {
        byte vk = MemoryApi.VkKeyScan(ch);
        PressKey((MemoryApi.KeyCode)vk, press);
    }

    public static void PressKey(MemoryApi.KeyCode vk, bool press)
    {
        ushort scanCode = (ushort)MemoryApi.MapVirtualKey((ushort)vk, 0);

        //Console.WriteLine("SendInput:: VK: " + (ushort)vk + " (" + vk + ") <-> SC: " + (ushort)(scanCode & 0xff));

        if (press)
            KeyDown(scanCode);
        else
            KeyUp(scanCode);
    }

    public static void KeyDown(ushort scanCode)
    {
        //Console.WriteLine("Key Down (SC): " + (ushort)(scanCode & 0xff));
        MemoryApi.INPUT[] inputs = new MemoryApi.INPUT[1];

        inputs[0].type = MemoryApi.INPUT_KEYBOARD;
        inputs[0].ki.wScan = (ushort)(scanCode & 0xff);
        inputs[0].ki.dwFlags = MemoryApi.KEYEVENTF_SCANCODE;
        inputs[0].ki.time = 0;
        inputs[0].ki.dwExtraInfo = IntPtr.Zero;

        uint intReturn = MemoryApi.SendInput(1, inputs, Marshal.SizeOf(inputs[0]));
        if (intReturn != 1)
        {
            throw new Exception("Could not send key: " + scanCode);
        }
    }

    public static void KeyUp(ushort scanCode)
    {
        //Console.WriteLine("Key Up (SC): " + scanCode);
        MemoryApi.INPUT[] inputs = new MemoryApi.INPUT[1];

        inputs[0].type = MemoryApi.INPUT_KEYBOARD;
        inputs[0].ki.wScan = (ushort)(scanCode & 0xff);
        inputs[0].ki.dwFlags = MemoryApi.KEYEVENTF_SCANCODE | MemoryApi.KEYEVENTF_KEYUP;
        inputs[0].ki.time = 0;
        inputs[0].ki.dwExtraInfo = IntPtr.Zero;

        uint intReturn = MemoryApi.SendInput(1, inputs, Marshal.SizeOf(inputs[0]));
        if (intReturn != 1)
        {
            throw new Exception("Could not send key: " + scanCode);
        }
}