среда, 23 июня 2010 г.

Вы не можете эмулировать ввод с клавиатуры с помощью PostMessage

Это перевод You can't simulate keyboard input with PostMessage. Автор: Реймонд Чен.

Некоторые люди предлагают эмулировать ввод с клавиатуры для приложения отправкой ему соответствующих клавиатурных сообщений, но это ненадёжно по многим причинам.

Во-первых, клавиатурный ввод - это более сложная концепция, чем буквы, напечатанные на английской клавиатуре. Языки, имеющие штриховые метки с буквами, имеют т.н. мёртвые клавиши, дальневосточные языки имеют кучу IME, и я понятия не имею, как обрабатывают ввод сложные языки с иероглифами. Иными словами, ввод символа - это нечто большее, чем просто нажатие на кнопку.

Во-вторых, даже если вам удастся отправить нужные сообщения ввода в очередь ввода целевого окна, это не установит/обновит модификаторы клавиатуры (shift states). Когда обработчик клавиатурного сообщения в этом окне вызовет функцию GetKeyState или GetAsyncKeyState, то он увидит "настоящее" состояние дел, а не фальшивое, которое вы хотели ему подсунуть, отправляя сообщения.

Функция SendInput была создана именно для этой цели: внедрение ввода в Windows. Если вы используете эту функцию, то как минимум состояние клавиатуры для приложения будет соответствовать вашим ожиданиям (хотя я не уверен, как она себя поведёт для сложных методов ввода).

5 комментариев:

  1. SendInput не всегда спасает ситуацию. Мне понадобилось при переходе по Tab на поле ввода выделять текст, но так, чтобы курсор находился в начале строки - не получилось. Посылал последовательно End, Shift+Home. Спасла функция PostKeyExHWND.

    ОтветитьУдалить
  2. Да, забавный комментарий. Почему забавный? Потому что ваша PostKeyExHWND - просто обёртка к SendInput (формально она вызывает keybd_event, но keybd_event - это wrapper для SendInput).

    Вывод: просто не смогли правильно вызвать SendInput.

    ОтветитьУдалить
  3. http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=856690&msg=10774450

    Yes, we can

    ОтветитьУдалить
  4. Алексей, Доброго Вам!
    Пробовал использовать функцию SendInput с флагом KEYEVENTF_UNICODE, замечательная штука!
    Но, то ли я не разобрался в чем то главном, то ли хочу странного, то ли ...
    Попробовал отправить с этим флагом многострочный текст с выравниванием строк табуляцией - на принимающей стороне все уложилось в одну строку, вместо переводов строк и табуляций - квадратики. Вернулся к каноническому: текст с флаком KEYEVENTF_UNICODE, переводы строк и табуляция - SendInput и сканкоды.
    Но всеравно, теплится грешная мысль, а вдруг что то сделал не так, и таки можно многострочный текст пересылать с флагом KEYEVENTF_UNICODE? Уж больно хорошо текст пересылается с этим флагом! Например, при передаче текста в полноэкранный RDP-сеанс, текст с этим флагом передается на ура, а вот переводы строки и табуляция, срабатывают через раз.
    Может Вы могли бы немного прояснить этот момент?
    Спасибо!

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.