Что точно устанавливает параметр charset CreateFont? - PullRequest
3 голосов
/ 17 июня 2011

Кодовая страница в моей Windows установлена ​​на ANSI (Latin1, Windows-1252).Я создаю шрифт с помощью CreateFont и передаю RUSSIAN_CHARSET в fdwCharSet

Вот что я испытываю:

  • Элементы управления Windows (как, например, Static), используя этот шрифт, игнорируют набор символов шрифта:строка, переданная в SetWindowTextA, отображается с латинскими символами
  • . После выбора этого шрифта в DC текстовые функции GDI (Ext) TextOutA и DrawTextA используют набор символов шрифта.Переданные им строки отображаются буквами кириллицы.

Почему?Когда учитывается параметр charset шрифта и когда он игнорируется?Могу ли я заставить элементы управления Windows использовать набор символов шрифта?

Ответы [ 4 ]

1 голос
/ 31 января 2012

Вам нужно будет преобразовать текст в Unicode и вызвать SetWindowTextW () вместо SetWindowTextA ().

Убедитесь, что класс окна зарегистрирован с помощью RegisterClassW (), а не RegisterClassA ().Это то, что действительно определяет, является ли окно юникодом.Вы можете использовать IsWindowUnicode (), чтобы убедиться, что окно фактически является юникодом.

Убедитесь, что вы передаете необработанные сообщения в DefWindowProcW (), а не в DefWindowProcA ().

Или, если окнодиалоговое окно, просто убедитесь, что оно создано с помощью CreateDialogW () или DialogBoxParamW ().

0 голосов
/ 05 июля 2019

Подумайте о перехвате gdi32full.dll GetCodePage, чтобы выбрать нужную вам кодовую страницу. CP_UTF8 например. Он имеет один указатель param, возвращает одиночный DWORD (кодовую страницу) и соглашение о вызовах stdcall.

0 голосов
/ 21 июня 2011

Вот что происходит:

  1. Вы вызываете SetWindowText с чем-то вроде "\xC4\xEE\xE1\xF0\xEE\xE5 xF3\xF2\xF0\xEE".
  2. Вы скомпилированы как приложение ANSI, а не Unicode, так что сопоставляется свызов SetWindowTextA.
  3. SetWindowTextA видит, что окно было создано в режиме ANSI, поэтому оно устанавливает строку напрямую.(Если бы это было окно Unicode, то оно преобразует входную строку ANSI в Unicode и передает ее в SetWindowTextW.)
  4. Окно ANSI преобразует строку ANSI в Unicode, чтобы оно могло ее отобразить.Но он не знает, что строка находится в другой кодовой странице, чем в системе по умолчанию.Именно это преобразование меняет все обратно на латинские символы.Предполагается, что входная строка находится в кодовой странице процесса по умолчанию (Windows 1252 в вашем случае).Так что теперь у вас есть куча латинских символов с ударениями вместо строки кириллицы.
  5. Элемент управления пытается отобразить эту строку Unicode, используя что-то вроде DrawTextW или TextOutW.
  6. Часть нижнего уровнясистема говорит: «О, дерьмо, эта строка представляет собой набор латинских символов, но пользователь выбрал кириллический шрифт».Чтобы решить проблему, он использует связывание шрифтов (или запасной вариант шрифта, я путаю эти термины), чтобы эффективно выбрать шрифт, совместимый с 1252.
  7. Вы видите латынь, вместо правильного русского.

Я пытался придумать минимальный способ сделать то, что вам нужно, но мне не удалось.Моей первой идеей было сделать преобразование самостоятельно и напрямую вызвать 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 для значимых элементов управления.

0 голосов
/ 21 июня 2011

> Могу ли я заставить элементы управления Windows использовать набор символов шрифта?

AFAIK нет, ты не можешь.

SetWindowTextA просто преобразует аргумент в Unicode, затем вызывает SetWindowTextW: и ядро ​​Windows, и оболочка, и GDI являются Unicode.

Чтобы преобразовать аргумент в Unicode, SetWindowTextA использует настройку региональных параметров Window («Язык для программ, не поддерживающих Unicode»).

...