C# 什么是;测试版:使用Unicode UTF-8实现全球语言支持”;真的吗?

C# 什么是;测试版:使用Unicode UTF-8实现全球语言支持”;真的吗?,c#,.net,windows,winforms,windows-10,C#,.net,Windows,Winforms,Windows 10,在一些Windows 10版本中(内部人员从2018年4月开始,也是“正常”1903),有一个新选项称为“Beta:使用Unicode UTF-8实现全球语言支持” 通过转到“设置”,然后执行以下操作,可以看到此选项: 所有设置->时间和语言->语言->管理语言设置 这就是它看起来的样子: 选中此复选框后,我观察到一些不规则情况(如下所示),我想知道此复选框的具体功能以及为什么会出现以下情况 在Visual Studio 2019中创建全新的Windows窗体应用程序。在主窗体上指定绘制偶数处

在一些Windows 10版本中(内部人员从2018年4月开始,也是“正常”1903),有一个新选项称为“Beta:使用Unicode UTF-8实现全球语言支持”

通过转到“设置”,然后执行以下操作,可以看到此选项: 所有设置->时间和语言->语言->管理语言设置

这就是它看起来的样子:

选中此复选框后,我观察到一些不规则情况(如下所示),我想知道此复选框的具体功能以及为什么会出现以下情况

在Visual Studio 2019中创建全新的Windows窗体应用程序。在主窗体上指定
绘制
偶数处理程序,如下所示:

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);
}
运行程序,如果未选中复选框,您将看到以下内容:

但是,如果选中复选框(并按要求重新启动),则会更改为:

你可以在维基百科上查找字体。根据给出的字符表,这两个字符的代码是
“\U0001F5D5\U0001F5D9”
。如果我使用它们而不是
“0r”
,则选中复选框即可工作,但如果不选中复选框,则现在看起来如下所示:

我想找到一个始终有效的解决方案,无论复选框是否选中

可以这样做吗?

您可以在ProcMon中看到它。 在
HKEY\U LOCAL\U MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage
65001

我不完全确定,但它可能与
KernelBase.dll
中的变量
gAnsiCodePage
有关,该变量
GetACP
读取。如果确实需要,您可以通过动态反汇编
GetACP
找到读取
gAnsiCodePage
的指令序列,并获取指向它的指针,然后直接更新变量,从而为您的程序动态更改它,而不必考虑系统设置


(事实上,我已经完成了这项工作,但我在我的系统上找不到该功能。不确定它是否仍然存在。)

大多数Windows C API有两种不同的变体:

  • “一种”变体,使用8位字符串和任何系统配置的编码。这取决于配置的国家/语言。 (Microsoft将配置的编码称为“ANSI代码页”,但实际上与ANSI无关)
  • “W”变体,在固定的几乎UTF-16编码中使用16位字符串。(之所以“几乎”是因为“未配对的代理”是允许的;如果你不知道这些是什么,那么不要担心它们)
微软的官方建议不是使用“A”版本,而是确保你的代码总是使用“W”变体。这样,无论用户的国家/语言配置为什么,您都应该获得一致的行为

然而,这个复选框似乎做了不止一件事。很明显,它应该将“ANSI代码页”更改为65001,这意味着UTF-8。看起来它也在改变字体呈现方式,使其更加统一


我建议您检测if==,然后绘制字符串的Unicode版本,否则绘制旧的“0r”版本。我不确定如何从.NET中执行此操作…

系统语言环境确定ANSI和OEM代码页。该复选框强制它们使用UTF-8(代码页65001)。显然,这有一个次要影响,导致
DrawText
不使用所选字体呈现“0r”。我猜这是因为Webdings和Wingding等符号字体在字体的OS/2表中没有任何Unicode范围或遗留代码页。相反,它们将代码映射到任意图示符。继续猜测,如果您选择常规字体,可能
“\U0001F5D5\U0001F5D9”
会起作用。显然,字体回退可以找到所需的字体。也许有用:除了前两句话,我只是在猜测。你比我更接近问题及其解决方案。如果你不介意的话,我希望你自己回答这个问题。你的源代码是用什么编码的?更改Windows设置将更改CP_ACP,这将更改没有显式编码(通过BOM)的文本文件中字符的解释。您的源似乎包含扩展字符。在源代码中,我建议对任何非ASCII字符使用字符串文本中的unicode转义码,否则您将取决于环境设置,环境设置可能会有所不同(在这种情况下会有所不同)。@PaulDempsey问题中给出了复制此代码的所有信息。没有进行OP中未提及的特殊编码更改。此外,我的源代码似乎不包含字符串文字中的unicode转义码以外的扩展字符,这些字符在OP中被标记为unicode转义码。谢谢,如果勾选UTF-8,值“ACPT”、“MACCP”和“OEMCP”确实会更改为65001。首先,您是如何发现这些是由UTF-8复选框修改的注册表值的?@JoakimThorén:您可以在中看到它?A变量与ANSI C、C89和C90一起使用。“W”变体不适用于ANSI C,在C95标准被广泛采用之前,它与portable('ANSI')C不兼容。@david:我指的是Windows特定的API,如CreateFileA/CreateFileW。它们完全独立于你使用的语言,无论是C、C++、Pascal或其他什么的修改。你说的是微软对官方C规范提出的修改,以添加更好的宽字符支持,这是另一回事(是C运行时的一部分,而不是核心OS API)。我是在评论你的断言,即ANSI API(可用于ANSI C)与ANSI无关。解释“A”后缀的来源:“Windows代码页,通常称为“ANSI代码页”,