Эмуляция нажатия клавиш с зажатым Shift'ом через SendInput

Тема в разделе "WASM.WIN32", создана пользователем Jin X, 21 окт 2018.

  1. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Приветствую всех!

    Использую SendInput для эмуляции набора текста и нажатия некоторых клавиш (по виртуальному номеру и скан-коду). Использую флаг KEYEVENTF_UNICODE для набора и флаг KEYEVENTF_SCANCODE для нажатия отдельных клавиш (ну или вообще без флага, см. далее). Для "отпускания" использую KEYEVENTF_KEYUP (хотя в случае набора текста всё прекрасно работает и без него).

    Набор текста, как я только что сказал, работает прекрасно. За исключением случаев, когда зажат Ctrl, Alt или Win – в этом случае срабатывает комбинация (т.е. если я посылаю T и зажат Ctrl, срабатывает Ctrl+T, по всей видимости), а вот зажатый Shift на это не влияет, как и всякие там Caps Lock и пр. Эту проблему решаю проверкой состояний Ctrl, Alt, Win (GetAsyncKeyState) и их отпусканием перед эмуляцией (через всё тот же SendInput).

    Нажатие клавиш тоже нормально работают (Enter, Tab и пр.), но есть нюанс. Очень странно срабатывают нажатия Ctrl, Alt, Shift. Например, если я посылаю последовательно VK_LSHIFT, VK_HOME, VK_HOME (KeyUp), VK_LSHIFT (KeyUp), VK_HOME, VK_HOME (KeyUp), то срабатывает только VK_HOME и VK_DEL, т.е. не выделяется и не удаляется текст до начала строки (удаляется только первая буква). Более того, если я использую флаг KEYEVENTF_SCANCODE, то не срабатывает и VK_DELETE, вместо этого печатается две запятых (вместо KeyDown и KeyUp)! Бред какой-то!

    При использовании KEYEVENTF_SCANCODE (для эмуляции Key) делаю так:
    Код (C++):
    1. input.Itype = INPUT_KEYBOARD;
    2. input.ki.dwFlags = KEYEVENTF_SCANCODE;  // при отпускании добавляется ещё и KEYEVENTF_KEYUP
    3. input.ki.wVk = Key;
    4. input.ki.wScan = MapVirtualKey(Key, 0);
    Вопросы:
    1. Как заставить срабатывать клавиши с Shift'ом (Ctrl, Alt)? GetAsyncKeyState(VK_LSHIFT) при этом показывает, что Shift нажат!
    2. Что за проблема с VK_DELETE ?
    3. Нужно ли использовать SendInout ещё раз с флагом KEYEVENTF_KEYUP при использовании KEYEVENTF_UNICODE ?
    --- Сообщение объединено, 21 окт 2018 ---
    Забавно, что последовательность VK_LSHIFT, VK_HOME, VK_HOME (KeyUp), VK_BACK, VK_BACK (KeyUp), VK_LSHIFT (KeyUp) срабатывает (правда, тут и Backspace срабатывает с Shift'ом).
    Т.е. отсылка VK_LSHIFT (KeyUp) получается убивает и выделение почему-то (это будет видно, если переставить VK_BACK (KeyUp) и VK_LSHIFT (KeyUp)). С VK_DELETE при установленном KEYEVENTF_SCANCODE не работает даже так.
     
    Последнее редактирование: 21 окт 2018
  2. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    369
    Адрес:
    Кольца Сатурна
    Разобрался. Нужно добавлять флаг KEYEVENTF_EXTENDEDKEY к VK_HOME (ну и к VK_DELETE можно, но тут непринципиально).

    А вот с VK_DELETE реально странно, т.к. при отсутствии флага KEYEVENTF_SCANCODE передаётся просто точка (VK_DELETE = '.'), а при добавлении скан-кода 53h (который возвращает MapVirtualKey, и он соответствует именно клавише Delete) вроде как система должна однозначно понимать, что это Delete. По факту же происходит всё наоборот.

    Третий вопрос остаётся открытым...