Поскольку TranslateMessage() возвращает ненулевое безоговорочно, как я могу сказать, до или после того факта, что перевод произошел?

Это продолжение того, что является правильным, современным способом обработки произвольного ввода текста в пользовательском элементе управления в Windows? WM_CHAR? IMM? TSF?,

Таким образом, после экспериментов с макетом без IME (американский английский), IME без TSF (японский FAKEIME из Windows XP DDK) и текстовой службой TSF (все, что поставляется с Windows 7), кажется, что если активный Профиль входного процессора не является текстовой службой ФБО (то есть это TF_PROFILETYPE_KEYBOARDLAYOUT), Мне все равно придется обрабатывать нажатия клавиш и WM_CHAR сообщения для ввода текста.

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

// if I can suppress WM_CHAR generation and synthesize it myself (including if the translation is just dead keys)
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
    if (WillTranslateMessage())
        InsertChar(GenerateEquivalentChar());
    else
        HandleRawKeyEvent();
    break;

// if I can know if a WM_CHAR was generated (or will be generated; for instance, in the case of dead keys)
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
    if (!DidTranslateMessage())
        HandleRawKeyEvent();
    break;
case WM_CHAR:
case WM_SYSCHAR:
    InsertChar(wParam);
    break;

Стандартный способ обработки ввода текста, как с клавиатуры, так и с помощью IME без TSF, - TranslateMessage() сделать WM_KEYDOWN -До- WM_CHAR перевод. Однако есть проблема: MSDN говорит

Если сообщение является WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN или WM_SYSKEYUP, возвращаемое значение отлично от нуля, независимо от перевода.

что означает, что я не могу использовать его, чтобы определить, произошел ли перевод.

Прочитав некоторые сообщения в блоге Майкла Каплана, я решил, что могу использовать ToUnicode() или же ToUnicodeEx() сделать преобразование самостоятельно, передавая в массиве состояний из GetKeyboardState(), Исходный код Wine, похоже, согласен, но в нем есть два особых случая, в которых я не уверен, являются ли они специфичными для вина или их нужно выполнять и на реальных Windows:

  • VK_PACKET - генерирует WM_CHAR прямо из сообщения LPARAM
  • VK_PROCESS - вызывает функцию ImmTranslateMessage() которая, кажется, является специфичной для вина функцией или недокументированной функцией imm32.dll; Я не могу сказать, что это правда

И вино тоже ничего не делает с WM_KEYUP а также WM_SYSKEYUP; опять же, я не знаю, правда ли это только для вина.

Но мне даже нужно беспокоиться об этих случаях в программе, которая использует TSF? И если я это сделаю, каков "официальный" способ сделать это? И даже тогда, что я буду делать на WM_KEYUP / WM_SYSKEYUP; мне нужно отправить их ToUnicode() тоже? Мне даже нужно поймать WM_KEYUP в моих окнах, особенно если там был WM_CHAR?

Или я пропускаю что-то, чего нет ни в одном из примеров MSF TSF, что позволит мне просто позаботиться о TF_PROFILETYPE_KEYBOARDLAYOUT Процессоры? Я думал, что TSF сделал прозрачный проход IME, но мой эксперимент с образцом FAKEIME показал иначе...? Я вижу, что Firefox и Chromium также проверяют TF_PROFILETYPE_KEYBOARDLAYOUT и даже использовать ImmGetIMEFileName() чтобы увидеть, поддерживается ли раскладка клавиатуры IME или нет, но я не знаю, действительно ли они позаботятся о вводе сами в этих случаях...

Моя минимальная версия сейчас Windows 7.

Благодарю.

ОБНОВЛЕНИЕ Оригинальная версия этого вопроса включала необходимость знать о связанных WM_KEYUP s; при втором просмотре моего эквивалентного кода на других платформах это не понадобится, за исключением деталей TranslateMessage(); Я скорректировал вопрос соответственно. (В OS X вы даже не отправляете события отпускания клавиш в систему ввода текста; в GTK+ вы делаете, но кажется, что нажатия клавиш, которые вставляют символы, не влияют на релизы и поэтому не обрабатываются в любом случае, по крайней мере, для методы ввода, которые я пробовал (могут быть некоторые, которые делают...). При этом, если я что-то пропустил, я добавил еще один подвопрос.

2 ответа

Решение

В общем, не стоит пытаться дублировать внутренние компоненты Windows. Это утомительно, подвержено ошибкам и может измениться без уведомления.

Элементы управления редактированием, к которым у меня есть доступ к источнику, для выбора клавиш со стрелками (и других определенных клавиш) в обработчике WM_KEYDOWN и передачи всего остального в обработчик по умолчанию, который (в конце концов) будет генерировать входные вызовы WM_CHAR или TSF (если ваш элемент управления поддерживает TSF, который он должен).

Вам все еще понадобится WM_CHAR в случае, если не задействован обработчик ФБО. Однако вы всегда можете заставить свой обработчик WM_CHAR вызывать ваш метод ITextStoreACP::InsertTextAtSelection.

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

Я считаю, что вы можете использовать TranslateMessageEx, возможно, с установленным битом 1 флага. В противном случае вы можете вызвать PeekMessage(PM_NOREMOVE) и проверить, возвращает ли он сообщение WM_CHAR для того же окна.

Другие вопросы по тегам