C#无法在不同版本的Windows之间显示unicode卡套

时间:2018-12-17 02:51:07

标签: c# unicode console-application

使用c#.net 4.7.1,我试图制作一个控制台应用程序21点游戏,但在使用不同版本的Windows的控制台输出中显示卡套时遇到麻烦。对于Windows 7,这是Main方法,可以正确显示西装:

static void Main(string[] args)
{
    string[] Suits = new string[] { "♠", "♣", "♥", "♦" };
    Methods.Print(Suits[0] + " " + Suits[1] + " " + Suits[2] + " " + Suits[3]);
    Console.ReadLine();
    ....
}

西服会根据需要显示,如下所示:

enter image description here

但是,如果我在Windows 10计算机上使用此Main方法运行程序,它们将显示为:

enter image description here

我发现,如果我在Windows 10计算机上的Main方法中包括此行,则西装将按照我希望的方式显示:

Console.OutputEncoding = System.Text.Encoding.UTF8;

但是那样就使西装无法在我的Windows 7计算机上正确显示。不管程序运行在什么Windows OS上,任何人都可以帮助我如何正确显示这些西装套装吗?预先感谢。

2 个答案:

答案 0 :(得分:0)

如果您希望它在控制台中可靠地工作,那么这是我的解决方案:

static void Main(string[] args)
{
    Console.WriteLine("D, C, H, S");
    Console.ReadLine();
}

还有其他2种选择:

  • 使用Encoding.UTF8检查Windows版本并测试所有方案;
  • Gui应用程序。

Windows 7

Windows7控制台和

的问题
Console.OutputEncoding = Encoding.UTF8;
Console.WriteLine("♠, ♣, ♥, ♦");
Console.ReadLine();

最有可能是控制台应用程序中的字体。

来自Console.OutputEncoding Property

  

请注意,要成功向控制台显示Unicode字符,需要满足以下条件:

     

控制台必须使用TrueType字体(例如Lucida Console或Consolas)来显示字符。

您可以在Console应用的属性中更改字体:

enter image description here

答案 1 :(得分:0)

感谢@tymtam对我遇到的问题的见解。我研究了更改控制台字体作为解决方案的可能性。我发现this文章显示了如何以编程方式将控制台字体更改为Lucida Console,这是一种真正的字体。这是该链接中的格式化代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;

namespace BlackJack
{
    class BlackJack
    {       
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool SetCurrentConsoleFontEx(IntPtr consoleOutput, bool maximumWindow, ref CONSOLE_FONT_INFO_EX consoleCurrentFontEx);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr GetStdHandle(int dwType);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern int SetConsoleFont(IntPtr hOut, uint dwFontNum);

        private const int STD_OUTPUT_HANDLE = -11;
        private const int TMPF_TRUETYPE = 4;
        private const int LF_FACESIZE = 32;
        private static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        internal unsafe struct CONSOLE_FONT_INFO_EX
        {
            internal uint cbSize;
            internal uint nFont;
            internal COORD dwFontSize;
            internal int FontFamily;
            internal int FontWeight;
            internal fixed char FaceName[LF_FACESIZE];
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct COORD
        {
            internal short X;
            internal short Y;

            internal COORD(short x, short y)
            {
                X = x;
                Y = y;
            }
        }

        public static void SetConsoleFont(string fontName = "Lucida Console")
        {
            unsafe
            {
                IntPtr hnd = GetStdHandle(STD_OUTPUT_HANDLE);
                if (hnd != INVALID_HANDLE_VALUE)
                {
                    CONSOLE_FONT_INFO_EX info = new CONSOLE_FONT_INFO_EX();
                    info.cbSize = (uint)Marshal.SizeOf(info);

                    // Set console font to Lucida Console.
                    CONSOLE_FONT_INFO_EX newInfo = new CONSOLE_FONT_INFO_EX();
                    newInfo.cbSize = (uint)Marshal.SizeOf(newInfo);
                    newInfo.FontFamily = TMPF_TRUETYPE;
                    IntPtr ptr = new IntPtr(newInfo.FaceName);
                    Marshal.Copy(fontName.ToCharArray(), 0, ptr, fontName.Length);

                    // Get some settings from current font.
                    newInfo.dwFontSize = new COORD(info.dwFontSize.X, info.dwFontSize.Y);
                    newInfo.FontWeight = info.FontWeight;
                    SetCurrentConsoleFontEx(hnd, false, ref newInfo);
                }
            }
        }

        static void Main(string[] args)
        {            
            Console.OutputEncoding = System.Text.Encoding.UTF8;
            SetConsoleFont();
            ....
        }

需要注意的两件事

  1. 我必须添加using语句才能使其正常工作:

    using System.Runtime.InteropServices;

  2. 我必须选中Allow unsafe code屏幕上的Project>Properties>Build复选框,如下所示:

enter image description here

进行了这些更改后,该程序可以在Windows 7和Windows 10上运行,并且会按我的意愿显示卡片套装。就像我之前说过的那样,我无权访问装有其他版本Windows的计算机,因此只能肯定地说它可以在Windows 7和Windows 10上运行。