среда, 22 декабря 2010 г.

Как [то, что вызывают] общие элементы управления, конвертирует строки между ANSI и Unicode?

Это перевод How do[es what] the common controls [call ]convert between ANSI and Unicode? Автор: Майкл Каплан.

Ранее Реймонд Чен писал о том, Как общие элементы управления конвертируют строки между ANSI и Unicode?, отвечая на вопрос в его suggestion box:
В контексте ansi (не unicode) приложения: как общие элементы управления (к примеру, listview) решают, какую использовать кодовую страницу для перевода многобайтовых строк в widestring?

Мне пришлось отлаживать ansi приложение, которое показывало испорченные строки на системе с традиционным китайским, потому что шрифт диалога привёл к тому, что listview использовал иную кодовую страницу, нежели системную ACP, при переводи multibyte в widechar.
Хотя я редко, если вообще когда-нибудь, не соглашусь с чем-то, что исходит из лагеря команды Оболочки, конкретно в этом случае я знаю два конкретных исключения из правила CP_ACP, которое вы обычно видите, хотя эти отличия могут иметь мало общего с кодом Shell / comctl32, так что Реймонд может быть прав в своей области :-)

Вот два других поведения, с которыми я встречался в различных версиях общих элементов управления:
  • Использование кодовой страницы потока (CP_THREAD_ACP)1.
  • Использование кодовой страницы, ассоциированной с набором символов шрифта, выбранного в контекст устройства.
Я, честно, не много знаю насчёт первого случая, но я помню баг-отчёты, когда изменение локали потока (что меняет и кодовую страницу потока) меняло поведение. В особенности в элементах управления < 6.0, где был настоящий ANSI+ код, пытающийся подняться над CP_ACP. Так что хотя у меня нет доказательств на этот счёт, это вполне может быть правдой.

Насчёт второго случая у меня есть больше информации, поскольку мне приходилось отлаживать его несколько раз - в общем говоря, текст не всегда конвертировался в Unicode; и ANSI-текст отправлялся в GDI с DC, содержащим установленный шрифт, использующий другую кодовую страницу, отличную от CP_ACP. Тогда GDI будет выполнять свою работу по отрисовке текста и делать при этом свой выбор, как будто его об этом просили - в своей странной и не всегда понятной манере.

Как правило, каждй раз, когда команда GDI пытается залезть в область NLS, результаты получаются предсказуемыми - бажный код, всегда. Отсюда мы имеем проблемы вроде тех, что я указал здесь. Между этой проблемой и проблемой, обсуждаемой здесь и здесь, ясно одно: ребятам из GDI следует подумать, не зайти ли им в гости к команде NLS и не натянуть ли им всем трусы.

Просто шучу, но вы знаете, что я имел в виду.

Для общих элементов управления же, когда я работал над MSLU, я встречался со случаями, когда мне приходилось использовать код вроде такого, чтобы всё работало:
function CpgFromHdc(dc: HDC): UINT;
var
  chs: Cardinal;
  csi: TCharsetInfo;
begin
  chs := GetTextCharset(dc);
  if TranslateCharsetInfo(chs, csi, TCI_SRCCHARSET) then
    Result := csi.ciACP
  else
    Result := g_acp;
end;
Так что, в любом случае, правило с CP_ACP должно быть единственным, но в Windows есть слишком много кусков кода, которые думают, что они лучше знают, что использовать...

С другой стороны, как и я - UNICODE! :-)

1 - Теперь вы знаете, что я чуствую насчёт этого, если вы читали Ничто не пахнет хуже локали потока, чем кодовая страница потока. Я думаю, что я тогда достаточно прямолинейно сказал.

This blog brought to you by ਸ਼ (U+0a36, aka GURMUKHI LETTER SHA)

Комментариев нет:

Отправить комментарий

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.

Примечание. Отправлять комментарии могут только участники этого блога.