Хвалёный Уникод не работает
Модераторы: Duncon, Hawk, Romeo, Eugie
-
- Сообщения: 12
- Зарегистрирован: 11 авг 2009, 16:24
Текст в Уникоде отображается в Комбобоксе и Ричедите неправильно. Combobox съедает значки над буквами, а Richedit заменяет нетривиальные буквы вопросительными значками. Английские буквы отображаются правильно. TextOutW отображает весь текст правильно.
Наверно caм что-то делаешь неправильно.
Поумнеть несложно, куда труднее от дури избавиться.
Чтобы контролы правильно отрисовывали Unicode-строки, должны выполняться несколько условий:
- версия ОС должна поддерживать Unicode (для современных версий Windows выполняется автоматически);
- само приложение должно быть скомпилировано с поддержкой Unicode (это важно, т.к. почти все функции WinAPI, принимающие строки в качестве параметров, существуют в 2 версиях - ANSI и WideChar(Unicode) - вот почему, кстати, TextOutW работает нормально);
- шрифт контрола должен поддерживать соответствующий набор символов. Например, по умолчанию часто используется растровый MS Sans Serif - естественно, не стоит ждать, что он корректно отобразит иероглифы
- версия ОС должна поддерживать Unicode (для современных версий Windows выполняется автоматически);
- само приложение должно быть скомпилировано с поддержкой Unicode (это важно, т.к. почти все функции WinAPI, принимающие строки в качестве параметров, существуют в 2 версиях - ANSI и WideChar(Unicode) - вот почему, кстати, TextOutW работает нормально);
- шрифт контрола должен поддерживать соответствующий набор символов. Например, по умолчанию часто используется растровый MS Sans Serif - естественно, не стоит ждать, что он корректно отобразит иероглифы

-
- Сообщения: 12
- Зарегистрирован: 11 авг 2009, 16:24
Вот и хочу знать, что я делаю неправильно.Decoder писал(а):Наверно caм что-то делаешь неправильно.
Пишу командой SendMessageW.
Что ещё нужно для счастья?
См здесь:
http://msdn.microsoft.com/en-us/library ... S.85).aspx (особенности поддержки Unicode для RichEdit)
http://www.codeguru.com/cpp/misc/misc/w ... php/c10251 (пример внедрения Unicode в ANSI приложение)
http://msdn.microsoft.com/en-us/library ... S.85).aspx (особенности поддержки Unicode для RichEdit)
http://www.codeguru.com/cpp/misc/misc/w ... php/c10251 (пример внедрения Unicode в ANSI приложение)
-
- Сообщения: 12
- Зарегистрирован: 11 авг 2009, 16:24
Работаю в Висте.Eugie писал(а):Чтобы контролы правильно отрисовывали Unicode-строки, должны выполняться несколько условий:
- версия ОС должна поддерживать Unicode (для современных версий Windows выполняется автоматически);
- само приложение должно быть скомпилировано с поддержкой Unicode (это важно, т.к. почти все функции WinAPI, принимающие строки в качестве параметров, существуют в 2 версиях - ANSI и WideChar(Unicode) - вот почему, кстати, TextOutW работает нормально);
- шрифт контрола должен поддерживать соответствующий набор символов. Например, по умолчанию часто используется растровый MS Sans Serif - естественно, не стоит ждать, что он корректно отобразит иероглифы![]()
Программа на Ассемблере. Пользуюсь правильной функцией для вывода -
SendMessageW.
А почему Sans Sherif не отобразит иероглифы? Для Sans Sherif Уникод другой?
Иероглифы мне рисовать и не нужно, только несколько европейских
кодировок да кириллицу.
Как сменить фонт? Я пытался в комбобоксе применять следующие эвиваленты команд C:
hDC = GetDC(hComboBox);
SelectObject(hDC, hFont);
Причём hFont применялся в других объектах и работает правильно (в том числе правильно пишет Уникод). Но в комбобоксе ничего не изменилось - ни фонт, ни отображение Уникода.
Как сменить фонт? Я пытался в комбобоксе применять следующие эвиваленты команд C:
hDC = GetDC(hComboBox);
SelectObject(hDC, hFont);
Это неправильно.
Передавать окну значение hFont нужно через сообщение WM_SETFONT.
SelectObject(hDC, hFont); нужно применять лишь в том случае, когда ты сам выполняешь отрисовку данного контрола в обработчике сообщения WM_PAINT.
Здесь ещё играет роль кодировка самой строки.
Если в С++ написать код:
то компилятор сам преобразует данную строку в кодировку UNICODE.
Если строка изначально была представлена как массив однобайтовых символов, то её нужно будет преобразовать в UNICODE с помощью функции MultibyteToWideChar. Причём исходная строка должна быть записана в кодировке Windows-1251, а не в кодировке OEM (DOS-866). Вполне возможно что исходный текст программы был набран в кодировке OEM (если код писался не в Visual Studio, а в другом редакторе).
Если в С++ написать код:
Код: Выделить всё
LPWSTR wszText = L"Привет всем!";
Если строка изначально была представлена как массив однобайтовых символов, то её нужно будет преобразовать в UNICODE с помощью функции MultibyteToWideChar. Причём исходная строка должна быть записана в кодировке Windows-1251, а не в кодировке OEM (DOS-866). Вполне возможно что исходный текст программы был набран в кодировке OEM (если код писался не в Visual Studio, а в другом редакторе).
Поумнеть несложно, куда труднее от дури избавиться.
Дело в том, что растровые шрифты не поддерживают Unicode. Они разработаны для 8-битной кодировки символов, поэтому никак не могут отображать полный набор Unicode. Грубо говоря, растровый шрифт - это набор битмапов для какого-то конкретного набора символов (character set), причем не более 255. Современные шрифты TrueType и OpenType - это скорее программа на спец. языке, каждый символ представляет что-то типа метафайла для отрисовщика. Такая технология позволяет "красиво" масштабировать шрифт, вращать и т.д. - короче, делает его device independent. И главное, в контескте вашего вопроса, снимает ограничение на размер набора символов. Но из практических соображений даже TT/OT шрифты не поддерживает полный набор символов Unicode. Запустите замечательную программу "Таблица символов" и поиграйтесь с параметрами Набор символов и Группировка - увидите сами.А почему Sans Sherif не отобразит иероглифы? Для Sans Sherif Уникод другой?
Если вам достаточно только кириллицы и расширенного набора латиницы с диакритическми знаками, вам подойдет практически любой TT/OT шрифт.
Собственно, WinMain ответил. Могу только добавить, что если контролы лежат на диалоговом окне, для которого установлены стили DS_SETFONT либо DS_SHELLFONT, оно само рассылает сообщение WM_SETFONT дочерним окнам, используя шрифт, указанный в секции FONT шаблона диалога (обычно это системный растровый шрифт). В этом случае нужно устанавливать нужный шрифт для контрола в обработчике сообщения WM_INITDIALOG.Как сменить фонт?
Еще совет: не пытайтесь самостоятельно обрабатывать WM_PAINT для стандартных контролов. Не буду объяснять почему, просто поверьте на слово

-
- Сообщения: 12
- Зарегистрирован: 11 авг 2009, 16:24
Прочитал первую ссылку. Заменил класс "RichEdit20A" на "RichEdit20W" - ничего не изменилось.Eugie писал(а):См здесь:
http://msdn.microsoft.com/en-us/library ... S.85).aspx (особенности поддержки Unicode для RichEdit)
http://www.codeguru.com/cpp/misc/misc/w ... php/c10251 (пример внедрения Unicode в ANSI приложение)
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
Я явно преобразовывал при помощи MultibyteToWideChar. Переводилось правильно, так как TextOutW выводит правильно. Программа новая, не набиралась в ДОСе.Decoder писал(а):Здесь ещё играет роль кодировка самой строки.
Если в С++ написать код:то компилятор сам преобразует данную строку в кодировку UNICODE.Код: Выделить всё
LPWSTR wszText = L"Привет всем!";
Если строка изначально была представлена как массив однобайтовых символов, то её нужно будет преобразовать в UNICODE с помощью функции MultibyteToWideChar. Причём исходная строка должна быть записана в кодировке Windows-1251, а не в кодировке OEM (DOS-866). Вполне возможно что исходный текст программы был набран в кодировке OEM (если код писался не в Visual Studio, а в другом редакторе).
--------------------------------------------------------------------------------
Добавлено сообщение
--------------------------------------------------------------------------------
WM_SETFONT правильно устанавливает фонт. Однако выводится Уникод всё равно неправильно, съедает значок над буквой. Тот же фонт при помощи TextOutW выводится правильно.WinMain писал(а):Это неправильно.
Передавать окну значение hFont нужно через сообщение WM_SETFONT.
SelectObject(hDC, hFont); нужно применять лишь в том случае, когда ты сам выполняешь отрисовку данного контрола в обработчике сообщения WM_PAINT.