Что на самом деле делает "Бета: использование Unicode UTF-8 для поддержки языков во всем мире"?

В некоторых сборках Windows 10 (инсайдеры, начиная с апреля 2018 года, а также в "обычном" 1903 году) есть новая опция под названием "Бета: использование Unicode UTF-8 для всемирной языковой поддержки".

Вы можете увидеть эту опцию, перейдя в Настройки, а затем: Все настройки -> Время и язык -> Язык -> "Настройки административного языка"

Вот как это выглядит:

Когда этот флажок установлен, я наблюдаю некоторые нарушения (ниже), и я хотел бы знать, что именно делает этот флажок и почему происходит следующее.

Создайте новое приложение Windows Froms в Visual Studio 2019. В главной форме укажите Paint даже обработчик следующим образом:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    Font buttonFont = new Font("Webdings", 9.25f);
    TextRenderer.DrawText(e.Graphics, "0r", buttonFont, new Point(), Color.Black);
}

Запустите программу, вот что вы увидите, если флажок НЕ установлен:

Однако, если вы установите флажок (и перезагрузите компьютер в соответствии с запросом), это изменится на:

Вы можете посмотреть шрифт Webdings в Википедии. Согласно приведенной таблице символов коды для этих двух символов "\U0001F5D5\U0001F5D9", Если я использую их вместо "0r" он работает с установленным флажком, но без установленного флажка теперь выглядит так:

Я хотел бы найти решение, которое всегда работает и не подвержено никаким изменениям, независимо от того, установлен флажок или нет.

Можно ли это сделать?

4 ответа

Вы можете увидеть это в ProcMon. Кажется, чтобы установить REG_SZ ценности ACP, MACCP, а также OEMCP в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage в 65001,

Я не совсем уверен, но это может быть связано с переменной gAnsiCodePage в KernelBase.dll, который GetACP читает. Если вы действительно хотите, вы можете изменить его динамически для вашей программы независимо от настроек системы путем динамической разборки GetACP найти последовательность команд, которая читает gAnsiCodePage и получить указатель на него, затем обновить переменную напрямую.

(На самом деле, я вижу ссылки на недокументированную функцию с именемSetCPGlobal это сделало бы эту работу, но я не могу найти эту функцию в моей системе. Не уверен, что он все еще существует.)

Посмотрите на этот вопрос, чтобы узнать, что он решает, когда он включен: Как сохранить в Powershell вывод программы в формате, отличном от ascii?

Также я нашел полезным объяснение, написанное Гислером (источник):

Если вы отметите этот параметр, Windows будет использовать кодовую страницу 65001 (UnicodeUTF-8) вместо локальной кодовой страницы, такой как 1252 (Western Latin1), для всех текстовых файлов. Преимущество состоит в том, что текстовые файлы, созданные, например, в русской локали, также могут быть прочитаны в другой локали, например, в Западной или Центральной Европе. Обратной стороной является то, что программы только для ANSI (большинство старых программ) будут отображать мусор вместо символов с диакритическими знаками.


Я оставляю здесь два способа включить его, я думаю, они будут полезны многим пользователям:

  1. Win+R -> intl.cpl
  2. Administrative вкладка
  3. Щелкните значок Change system locale кнопка.
  4. Давать возможность Beta: Use Unicode UTF-8 for worldwide language support

или, альтернативно, через reg файл:

      Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage]
"ACP"="65001"
"OEMCP"="65001"
"MACCP"="65001"

Большинство API-интерфейсов Windows C представлены в двух вариантах:

  • Вариант "A", использующий 8-битные строки с любой кодировкой, сконфигурированной системой. Это зависит от настроенной страны / языка. (Microsoft называет настроенную кодировку "Кодовой страницей ANSI", но на самом деле это не имеет ничего общего с ANSI).
  • Вариант "W", использующий 16-битные строки в фиксированной кодировке почти UTF-16. ("Почти" означает, что "непарные суррогаты" разрешены; если вы не знаете, что это такое, не беспокойтесь о них).

Официальный совет Microsoft - не использовать версии "A", но чтобы ваш код всегда использовал варианты "W". Таким образом, вы должны добиться согласованного поведения независимо от страны / языка пользователя.

Однако похоже, что этот флажок выполняет несколько функций. Понятно, что предполагается изменить "Кодовую страницу ANSI" на 65001, что означает UTF-8. Похоже, он также меняет рендеринг шрифтов, чтобы он стал более Unicody.

Я предлагаю вам определить, если GetACP() == 65001, затем нарисовать версию Unicode ваших строк, в противном случае нарисуйте старую версию "0r". Я не уверен, как это сделать из.NET...

На моих окнах, когда я проверил Beta: Use Unicode UTF-8 for worldwide language support. Следующие значения regedit в HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePageизмененный.

      ACP: 936 -> 65001
MACCP: 10008 -> 65001
OEMCP : 936 -> 65001

Если я не проверил, то компиляция визуальной студии не удалась с Exception: Bad UTF-8 encoding (U+FFFD; REPLACEMENT CHARACTER) found while decoding string: ..., если я проверял, то компиляция прошла успешно, но ос заполнена нечитаемым кодом.

Другие вопросы по тегам