Что на самом деле делает "Бета: использование 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 (большинство старых программ) будут отображать мусор вместо символов с диакритическими знаками.
Я оставляю здесь два способа включить его, я думаю, они будут полезны многим пользователям:
- Win+R ->
intl.cpl
-
Administrative
вкладка - Щелкните значок
Change system locale
кнопка. - Давать возможность
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: ...
, если я проверял, то компиляция прошла успешно, но ос заполнена нечитаемым кодом.