Вот что происходит:
- Вы вызываете SetWindowText с чем-то вроде
"\xC4\xEE\xE1\xF0\xEE\xE5 xF3\xF2\xF0\xEE"
.
- Вы скомпилированы как приложение ANSI, а не Unicode, поэтому это соответствует вызову SetWindowTextA.
- SetWindowTextA видит, что окно было создано в режиме ANSI, поэтому устанавливает строку напрямую. (Если бы это было окно в формате Unicode, то оно преобразовывало бы входную строку ANSI в Unicode и передало ее в SetWindowTextW.)
- Окно ANSI преобразует строку ANSI в Unicode, чтобы ее можно было отобразить. Но он не знает, что строка находится на другой кодовой странице, чем кодовая страница по умолчанию для системы. Именно это преобразование меняет все обратно на латинские символы. Предполагается, что входная строка находится на кодовой странице процесса по умолчанию (в вашем случае Windows 1252). Итак, теперь у вас есть куча латинских символов с диакритическими знаками вместо цепочки кириллических.
- Элемент управления пытается отобразить эту строку Unicode, используя что-то вроде DrawTextW или TextOutW.
- Нижняя часть системы говорит: «Вот дерьмо, эта строка состоит из набора латинских символов, но пользователь выбрал кириллический шрифт». Чтобы решить эту проблему, он использует привязку шрифтов (или резервный шрифт, я путаю эти термины), чтобы эффективно выбрать шрифт, совместимый с 1252.
- Вы видите латинскую абракадабру вместо собственно русской.
Я пытался придумать минимальный способ сделать то, что вам нужно, но мне это не удалось. Моей первой идеей было сделать преобразование самостоятельно и вызвать SetWindowTextW напрямую:
void SetWindowTextRussian(HWND hwnd, char *pszCyrillic) {
const int cchCyrillic = ::lstrlen(pszCyrillic);
const int cchUnicode = 4 * cchCyrillic; // worst case
WCHAR *pszUnicode = new WCHAR[cchUnicode];
// See: http://msdn.microsoft.com/en-us/library/dd317756(v=vs.85).aspx
const UINT CP_CYRILLIC = 1251;
if (::MultiByteToWideChar(CP_CYRILLIC, 0, pszCyrillic, -1,
pszUnicode, cchUnicode) > 0) {
::SetWindowTextW(hwnd, pszUnicode);
}
delete [] pszUnicode;
}
Но это не работает. Я подозреваю, что, поскольку окно было создано как окно ANSI, строка Unicode преобразуется обратно в ANSI (предполагая, что снова неправильная кодовая страница), и тогда вы получаете вопросительные знаки вместо латинской чепухи.
Я думаю, вам придется преобразовать приложение в Unicode или работать только с кодовой страницей по умолчанию, установленной на 1251.
Обновление: если вы управляете созданием окна (например, вы вызываете CreateWindow напрямую, а не создаете экземпляры элементов управления в диалоговом окне), то вы, вероятно, можете заставить вышеописанное работать, вызвав CreateWindowW напрямую и создав Окно Unicode для важных элементов управления.
person
Adrian McCarthy
schedule
21.06.2011