Каков правильный современный способ обработки произвольного ввода текста в пользовательском элементе управления в Windows? WM_CHAR? IMM? TSF?
Я хочу иметь возможность поддерживать ввод текста в пользовательском элементе управления Windows, так же, как это уже сделали EDIT и элементы управления rich edit, но не создавать подклассы. Элемент управления в настоящее время использует Direct2D и DirectWrite для рисования текста и работает в Windows Vista с пакетом обновления 1 (SP1) с обновлением платформы или более поздней версии (я мог бы изменить его на Windows 7 с пакетом обновления 1 (SP1) с обновлением платформы или более поздней версии, если решу, что мне нужны более новые функции Direct2D и DirectWrite, если они доступно там или только на Windows 8, но это другой вопрос...)
Для чего бы это ни стоило, в OS X I использовал бы NSTextInputClient, а в GTK+ я бы использовал GtkIMContext. Это такие вещи, о которых я говорю.
Очевидный выбор - использовать WM_CHAR
, который, если я правильно понял, изначально UTF-16, если класс окна зарегистрирован с RegisterClassW()
и поэтому должен "просто работать" независимо от местоположения. Тем не мение, WM_CHAR
генерируется TranslateMessage()
и его документация говорит, что нет никакого способа определить, является ли WM_CHAR
был создан или нет, так как TranslateMessage()
всегда возвращает ненулевое значение. Мне нужно иметь возможность определить, будет ли текущее сообщение клавиатуры обрабатываться текстовой системой (и, следовательно, должно игнорироваться); это особенно верно, поскольку все нетекстовые ключи должны обрабатываться независимо от макета (что у меня уже есть).
Я также видел в примерах кода Windows 7 для API IMM и Text Services Framework. Я не уверен, что один лучше другого, и они оба, кажется, делают то же самое. Они?
В случае с IMM существует ряд WM_IMM_xxx
сообщения, которые я не уверен, должен ли я игнорировать или нет, и каждая найденная мной ссылка, похоже, не согласна с тем, должен ли я обрабатывать их в окне Unicode или нет... Кроме того, вышеупомянутая проблема с определением, является ли данное ключевое событие будет обработано IMM или еще не открыто; есть ли способ?
У TSF есть концепция, называемая ACP, которая, кажется, позволяет мне использовать любой формат хранения текста, который я хочу для хранения текста, который я собираюсь использовать (т. Е. Не в процессе разработки). Это правда? Я хотел бы иметь возможность хранить свой текст как UTF-8 с атрибутами, преобразовывая в UTF-16 при рисовании (для DirectWrite). Позволяют ли мне делать другие варианты API?
Или я совершенно не на том пути?
И как мне выбрать экранную клавиатуру, как только я все это сделаю?
Другие ссылки, которые я использовал:
Благодарю.
ОБНОВЛЕНИЕ 7 ноября 2016
Посмотрев на образец TsfPad снова, я заметил, что он также, кажется, просто использует WM_CHAR
; теперь я не уверен, как это вообще использует TSF, кроме того, что это делает...
1 ответ
API TSF - это расширенный набор API IMM. Он также новее, чем IMM, и является современным современным способом обработки международного ввода текста (а также других механизмов ввода, таких как почерк и речь).
Если вы используете API TSF, текст отображается через API вместо сообщений Windows (поэтому вопрос о том, какое сообщение не имеет значения).
Экранная клавиатура обрабатывается автоматически, и вам не нужно об этом беспокоиться. (Цель TSF - сделать ваше приложение независимым от источника ввода.)
TSF может поддерживать UTF-8, но это немного болезненно; вам нужно пометить символы расширения как скрытые. Вам было бы намного лучше с UTF-16, который является API по умолчанию TSF.
Лучший пример, который я знаю о том, как добавить поддержку TSF в существующий элемент управления редактированием, - это статья, которую я написал еще в июле 2007 года.
Ввод все еще может поступать через WM_CHAR (например, если текущий профиль ввода представляет собой раскладку клавиатуры), поэтому вам необходимо реализовать это; тем не менее, как правило, вы можете обрабатывать сообщения WM_CHAR, вызывая свою реализацию ITextStoreACP::InsertTextAtSelection.