Я создал свое собственное однострочное управление текстовым полем в .net 3.5 C#
Я записал это полностью с нуля, включая мой собственный код выбора, прокрутку, скопировать/вставить и т.д. Это может даже выбрать слева направо текст, не, что я когда-либо использовал бы это...
Проблемой, которую я имею, является с IME (редактор метода ввода) интеграция. IME действительно работает до степени, но у меня есть несколько проблем. Я просто перечислю одного из них здесь.
Обычно, с помощью TextBox, конструкция IME представляется в TextBox. Однако в моем Управлении, IME отображен в правом нижнем углу экрана. Я пытался смотреть на другие пользовательские элементы управления, включал тот, используемый в SharpDevelop. Однако это имело ту же проблему. Вводя на китайском языке, японский язык или корейский язык заставил материал IME быть сделанным в правом нижнем углу экрана.
Мне нужны некоторые указатели о том, как заставить это быть сделанным в моем собственном текстовом поле, и я посмотрел на Windows API для IME, но существует столько функций, и я понятия не имею, где запустить.
Так, какие-либо идеи?
Хорошо, если какие-либо примеры кода находятся в (управляемом/неуправляемом) C++ или VB.net. Я могу преодолеть его достаточно легко.
Хорошо, похоже, что на StackOverflow не так много экспертов по IME ... или никого не интересует.
Как бы то ни было, я разобрался.
По сути, мне нужно перехватить следующие сообщения Windows:
WM_INPUTLANGCHANGE = 0x51
WM_KEYUP = 0x101
WM_CHAR = 0x102
WM_CONVERTREQUESTEX = 0x108
WM_IME_STARTCOMPOSITION = 0x10D
WM_IME_ENDCOMPOSITION = 0x10E
WM_IME_COMPOSITION = 0x10F
WM_IME_SETCONTEXT = 0x281
WM_IME_NOTIFY = 0x282
WM_IME_CONTROL = 0x283
WM_IME_COMPOSITIONFULL = 0x284
WM_IME_SELECT = 0x285
WM_IME_CHAR = 0x286
WM_IME_REQUEST = 0x0288
WM_IME_KEYDOWN = 0x290
WM_IME_KEYUP = 0x291
Я перехватываю WM_KEYUP
и WM_CHAR
, потому что если я щелкну где-нибудь в середине композиции корейского символа , Я не получаю сообщения о композиции, но, тем не менее, мне нужно добавить этот символ в текстовое поле. Это странное поведение, интересно, ошибка ли это.
Когда это происходит, корейцы, китайцы и японцы ведут себя по-разному.
Корейский - это действительно простой язык (хотя я не уверен, что такое преобразование ханджа, потому что я все равно не знаю, как его использовать).
Как правило, для всех языков, когда я получаю WM_IME_COMPOSITION
, я должен вызывать ImmGetCompositionString
в Imm32.dll, как я описал в ответе на этот вопрос . Затем я показываю это как незавершенную композицию, но не добавляю ее к сохраненному тексту.
Когда строка была составлена, сообщение Windows отличается для каждого IME. Каждый раз я могу получить его из сообщения WM_IME_COMPOSITION
.
В корейском языке LParam
будет просто GCS_RESULTSTR
, а WParam
будет введенным символом, который я могу просто преобразовать в char
] В японском языке «LParam» будет GCS_RESULTREADSTR | GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE
. Я должен использовать результат ImmGetCompositionString
, который я сохранил из предыдущего сообщения WM_IME_COMPOSITION, потому что в этот раз это будет пустая строка.
На китайском языке LParam
будет GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE
. Это то же самое, что и японский, за исключением случая, когда ранее сохраненная ImmGetCompositionString
пуста, и в этом случае мне нужно преобразовать WParam
в char.
Во всех трех случаях я должен убедиться, что мой отображаемый комп в процессе очистки очищен.
Если я получаю WM_IME_STARTCOMPOSITION
, я устанавливаю флаг компоновки (и показываю строку в процессе компоновки)
Если я получаю WM_IME_ENDCOMPOSITION
, я сбрасываю этот флаг (и снимаю компоновку) строка в процессе).
Иногда я не получаю WM_IME_ENDCOMPOSITION
, поэтому снимаю флажок при получении WM_CHAR
.
В общем, это был очень интересный опыт обучения, который все еще продолжается - но теперь, наконец, я могу использовать IME под моим контролем! Я оставался на работе до часу ночи, чтобы закончить.