Вопрос по c# – имитация события нажатия клавиши с использованием SendInput с C #

3

Следуя совету из этой темы:различать нажатие клавиш на клавиатуре Real и Virtual

Я пытаюсь создать программу, которая будет отправлять события нажатия клавиш на клавиатуре, используяSendInput() метод.

However, the problem is that when I try to simulate a key press event - nothing happens whatsoever. Пока это мой код:

    [DllImport("user32.dll")]
    static extern UInt32 SendInput(UInt32 nInputs, [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] INPUT[] pInputs, Int32 cbSize);

    [StructLayout(LayoutKind.Sequential)]
    struct KEYBDINPUT
    {
        public short wScan; public int dwFlags;
        public int time; public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Explicit)]
    struct INPUT
    {
        [FieldOffset(0)] public int type;
        [FieldOffset(8)]  public KEYBDINPUT ki; //x64 - 8, x32 - 4
    }

    const int KEYEVENTF_DOWN = 0; //key UP
    const int KEYEVENTF_EXTENDEDKEY = 0x0001;
    const int KEYEVENTF_KEYUP = 0x0002; //key UP
    const int KEYEVENTF_UNICODE = 0x0004;
    const int KEYEVENTF_SCANCODE = 0x0008; // scancode

    public void Send_Key(short Keycode)
    {
        INPUT[] InputData = new INPUT[1];
        InputData[0].type = 1;
        InputData[0].ki.wScan = Keycode;
        InputData[0].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE;
        InputData[0].ki.time = 0;
        InputData[0].ki.dwExtraInfo = IntPtr.Zero;
        SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));
    }

Чтобы расшифровать коды сканирования, я загрузил программу, предложенную в этой теме:

https://superuser.com/questions/293609/windows-7-tool-to-capture-keyboard-scan-codes

в соответствии с этой программой - & quot; a & quot; код клавиши для моей клавиатуры - "65";

Моя программа должна вызывать событие нажатия клавиши при изменении текста в текстовом поле, поэтому, если мы введем & quot; q & quot; - текст должен измениться на «q»; плюс результат send_key (), то есть "qa":

    private void textBox2_TextChanged(object sender, EventArgs e)
    {
        Send_Key(0x0065); // nothing happens (0x65 also fails)
    }

Что я делаю неправильно? В будущем я буду изменять этот код, чтобы я мог указать время удержания клавиши (между событиями ВНИЗ и ВВЕРХ). но сейчас для целей тестирования я имитирую только событие keyUP.

EDIT: Ганс, согласно твоему совету, это правка, но, к сожалению, она не работает.

 public void Send_Key(short Keycode)
        {
            INPUT[] InputData = new INPUT[1];
            InputData[0].type = 1;
            InputData[0].ki.wScan = Keycode;
            InputData[0].ki.dwFlags = KEYEVENTF_DOWN;
            InputData[0].ki.time = 0;
            InputData[0].ki.dwExtraInfo = IntPtr.Zero;

            uint intReturn = SendInput(1, InputData, Marshal.SizeOf(typeof(INPUT)));

            if (intReturn == 0) //!=1
            {
                throw new Exception("Could not send keyDOWN: " + Keycode);
            }

            INPUT[] InputData2 = new INPUT[1];
            InputData2[0].type = 1;
            InputData2[0].ki.wScan = Keycode;
            InputData2[0].mi.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP | KEYEVENTF_SCANCODE;
            InputData2[0].ki.time = 0;
            InputData2[0].ki.dwExtraInfo = IntPtr.Zero;

            uint intReturn2 = SendInput(1, InputData2, Marshal.SizeOf(typeof(INPUT)));

            if (intReturn2 == 0) //!=1
            {
                throw new Exception("Could not send keyUP: " + Keycode);
            }
        }

нет ошибок .. и нет вывода.

да, это действительно winforms. решил мою проблему, изменив код полностью (нашел его на каком-то форуме) и выбрав правильные коды сканирования с этой страницы:msdn.microsoft.com/en-us/library/aa299374(v=vs.60).aspx Например, чтобы напечатать & quot; a & quot; Я должен был ввести либо «30» или "0x1E" .. Alex
Я не на 100%, но я не думаю, что вы можете "добавить" например, напрямую от TextChanged - я думаю, вам придется создавать поток для этого - но это еще не все. В любом случае, зачем использовать это "для своего собственного приложения"? Вы используете win-формы? ... NSGaga
edit2: после любой неудачной попытки напечатать письмо, когда я закрываю свою программу - я не могу изменить вкладки в Google Chrome !!! Проверял эту вещь несколько раз - моя программа - причина! странный.. Alex

Ваш Ответ

1   ответ
2

Это нормально, я думаю, но это не заставит Windows делать что-либо. Чтобы сгенерировать нажатие клавиши, вы должны сначала отправить KEYDOWN. «Время удержания»; не имеет никакого полезного эффекта, поэтому просто поместите два вызова SendInput в один и тот же метод.

Вы должны добавить проверку ошибок, вызовы winapi не генерируют никаких исключений. Бросьте Win32Exception, если функция возвращает 0. И исправьте объявление [DllImport] с SetLastError = true.

Вы можете избежать использования той программы, которую вы нашли на superuser.com, установив вместо этого поле ki.wVk и опуская флаг KEYEVENTF_SCANCODE. Так что вы указываете виртуальные ключи вместо кодов сканирования.Тип перечисления ключей .NET дает вам ценности, которые вам нужны. Как Keys.A, чтобы сгенерировать нажатие клавиши для клавиши A.

Error: User Rate Limit Exceeded Alex
Error: User Rate Limit ExceededhaveError: User Rate Limit Exceeded

Похожие вопросы