En algunas compilaciones de Windows 10 (información privilegiada a partir de abril de 2018 y también "normal" 1903) hay una nueva opción llamada "Beta: use Unicode UTF-8 para compatibilidad con idiomas en todo el mundo".
Puede ver esta opción yendo a Configuración y luego: Todas las configuraciones -> Hora e idioma -> Idioma -> "Configuración administrativa de idioma"
Esto es lo que parece:
Cuando esta casilla de verificación está marcada, observo algunas irregularidades (a continuación) y me gustaría saber qué hace exactamente esta casilla de verificación y por qué sucede lo siguiente .
Cree una nueva aplicación de Windows Forms en su Visual Studio 2019. En el formulario principal, especifique el controlador de Paint
even de la siguiente manera:
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); }
Ejecute el programa, esto es lo que verá si la casilla de verificación NO está marcada:
Sin embargo, si marca la casilla de verificación (y reinicia cuando se le solicite), esto cambia a:
Puede buscar la fuente Webdings en Wikipedia. Según la tabla de caracteres dada, los códigos para estos dos caracteres son "\U0001F5D5\U0001F5D9"
. Si los uso en lugar de "0r"
, funciona con la casilla de verificación marcada, pero sin la casilla de verificación marcada, ahora se ve así:
Me gustaría encontrar una solución que siempre funcione, independientemente de si la casilla está marcada o no.
Se puede hacer esto?
Puedes verlo en ProcMon. Parece establecer los valores REG_SZ
ACP
, MACCP
y OEMCP
en HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage
en 65001
.
No estoy del todo seguro, pero podría estar relacionado con la variable gAnsiCodePage
en KernelBase.dll
, que lee GetACP
. Si realmente lo desea, es posible que pueda cambiarlo dinámicamente para su programa, independientemente de la configuración del sistema, desensamblando dinámicamente GetACP
para encontrar la secuencia de instrucciones que lee gAnsiCodePage
y obtener un puntero, luego actualizando la variable directamente.
(En realidad, veo referencias a una función no documentada llamada SetCPGlobal
que habría hecho el trabajo, pero no puedo encontrar esa función en mi sistema. No estoy seguro de si todavía existe).
Mire esta pregunta para ver qué resuelve cuando está habilitada: ¿Cómo guardar en un archivo la salida del programa que no es ascii en Powershell?
También encontré útil la explicación escrita por Ghisler ( fuente ):
Si marca esta opción, Windows utilizará la página de códigos 65001 (Unicode UTF-8) en lugar de la página de códigos local como 1252 (Western Latin1) para todos los archivos de texto sin formato. La ventaja es que los archivos de texto creados en, por ejemplo, la configuración regional rusa también se pueden leer en otra configuración regional, como Europa occidental o central. La desventaja es que los programas ANSI-Only (la mayoría de los programas más antiguos) mostrarán basura en lugar de caracteres acentuados.
Dejo aquí dos formas de habilitarlo, creo que serán de ayuda para muchos usuarios:
intl.cpl
Administrative
Change system locale
.Beta: Use Unicode UTF-8 for worldwide language support
o alternativamente a través del archivo de reg
:
Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage] "ACP"="65001" "OEMCP"="65001" "MACCP"="65001"
La mayoría de las API de Windows C vienen en dos variantes diferentes:
El consejo oficial de Microsoft es no usar las versiones "A", sino asegurarse de que su código siempre use las variantes "W". De esa manera, se supone que debe obtener un comportamiento consistente sin importar el país/idioma del usuario configurado.
Sin embargo, parece que esa casilla de verificación está haciendo más de una cosa. Está claro que se supone que debe cambiar la "Página de códigos ANSI" a 65001, lo que significa UTF-8. Parece que también está cambiando la representación de fuentes para que sea más Unicody.
Le sugiero que detecte si GetACP() == 65001 , luego dibuje la versión Unicode de sus cadenas; de lo contrario, dibuje la versión anterior "0r". No estoy seguro de cómo lo haces desde .NET...