Поскольку 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 для того же окна.