Неправильный ответ
Используйте WM_UNICHAR
, он обрабатывает UTF-32 и может обрабатывать символы дополнительной плоскости Unicode.
Хотя это почти правда, но полная истина выглядит так:
WM_UNICHAR
- это хак, разработанный для ANSI Windows для получения символов Unicode. Создайте окно Unicode, и вы никогда его не получите.
- Создайте окно ANSI, и вы будете удивлены, что оно все еще не работает должным образом. Уловка в том, что когда окно создано, вы получаете
WM_UNICHAR
с 0xffff
, на который вы должны отреагировать, вернув 1 (стандартная оконная процедура вернет 0). Не сделайте этого, и вы никогда не увидите WM_UNICHAR
снова. Хорошо, что официальная документация этого не говорит.
- Запустите вашу программу в системе, которая по загадочным причинам не поддерживает
WM_UNICHAR
(например, в моей системе Windows 7 64) и все равно не будет работать, даже если вы все делаете правильно.
Теоретически правильный ответ
Нечего проверять или на что обращать внимание.
Скомпилируйте с определенным UNICODE
или явным образом создайте свой класс окна, а также свое окно, используя функцию "W
", и используйте WM_CHAR
, как если бы это было наиболее естественным способом. Вот и все. Это действительно самая естественная вещь.
WM_CHAR
использует UTF-16 (кроме случаев, когда это не так, например, в Windows 2000). Конечно, один символ UTF-16 не может представлять кодовые точки вне BMP, но это не проблема, потому что вы просто получаете два WM_CHAR
сообщений, содержащих суррогатную пару. Это полностью прозрачно для вашего приложения, вам не нужно делать ничего особенного. Любая функция Windows API, которая принимает строку широких символов, также с радостью примет эти суррогаты.
Единственное, о чем нужно знать, это то, что теперь длина строки (очевидно) больше не является количеством 16-битных слов. Но, во всяком случае, это было неверное предположение.
Печальная правда
На самом деле, во многих (большинстве? Всех?) Системах вы просто получаете одно WM_CHAR
сообщение с wParam
, содержащее младшие 16 бит кода ключа. Что очень хорошо для всего в BMP, но в противном случае отстой.
Я проверил это как с помощью кодов Alt-клавиатуры, так и путем создания пользовательской раскладки клавиатуры, которая генерирует кодовые точки вне BMP. В любом случае принимается только один WM_CHAR
, содержащий младшие 16 бит символа. Старшие 16 бит просто выбрасываются.
Чтобы ваша программа работала на 100% правильно с Юникодом, вы, очевидно, должны использовать диспетчер методов ввода (ImmGetCompositionStringW
), что является неприятным и плохо документированным. Лично для меня это просто означает: «Хорошо, винт это». Но если вы заинтересованы в том, чтобы быть на 100% корректным, посмотрите на исходный код любого редактора, использующего Scintilla (ссылка на строку) , который делает именно это и работает отлично.