【问题标题】:Using WriteConsoleOutput on '/u263a' always prints incorrectly [duplicate]在“/u263a”上使用 WriteConsoleOutput 总是打印不正确[重复]
【发布时间】:2020-06-02 20:05:23
【问题描述】:

查看this question 并修改代码以打印诸如“☺”、“☻”或“█”之类的字符后,我看不出如何使用 WriteConsoleOutput 正确绘制这些字符。 (使用流或 Console.Write 时没有问题,但我无法使用这些解决方案单独控制字符颜色,因此它们不适合。)

似乎有一个针对 C++ 的解决方案 here,但他们在底部谈论的“L”宏不适用于 C#。

最后,在检查了here 的建议后,我看不出我最终得到的代码有什么问题:

class Program
{
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    static extern SafeFileHandle CreateFile(
        string fileName,
        [MarshalAs(UnmanagedType.U4)] uint fileAccess,
        [MarshalAs(UnmanagedType.U4)] uint fileShare,
        IntPtr securityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        [MarshalAs(UnmanagedType.U4)] int flags,
        IntPtr template
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool WriteConsoleOutputW(
        SafeFileHandle hConsoleOutput,
        CharInfo[] lpBuffer,
        Coord dwBufferSize,
        Coord dwBufferCoord,
        ref SmallRect lpWriteRegion
    );

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetConsoleOutputCP(uint wCodePageID);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetConsoleCP(uint wCodePageID);

    [StructLayout(LayoutKind.Sequential)]
    public struct Coord
    {
        public short X;
        public short Y;

        public Coord(short X, short Y)
        {
            this.X = X;
            this.Y = Y;
        }
    };

    [StructLayout(LayoutKind.Explicit)]
    public struct CharUnion
    {
        [FieldOffset(0)] public char UnicodeChar;
        [FieldOffset(0)] public byte AsciiChar;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct CharInfo
    {
        [FieldOffset(0)] public CharUnion Char;
        [FieldOffset(2)] public short Attributes;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SmallRect
    {
        public short Left;
        public short Top;
        public short Right;
        public short Bottom;
    }

    static void Main(string[] args)
    {
        //SetConsoleOutputCP(65001);
        //SetConsoleCP(65001);
        SafeFileHandle fileHandle = CreateFile("CONOUT$", 0x40000000, 2, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
        Console.TreatControlCAsInput = true;
        //Console.OutputEncoding = Encoding.UTF8;
        Console.OutputEncoding = System.Text.Encoding.Unicode;
        Console.CursorVisible = false;
        short screenWidth = 40;
        short screenHeight = 20;
        Console.SetWindowSize(screenWidth + 1, screenHeight + 1);
        Console.SetBufferSize(screenWidth + 1, screenHeight + 1);
        bool running = true;
        while (running)
        {
            CharInfo[] buf = new CharInfo[screenWidth * screenHeight];
            SmallRect rect = new SmallRect() { Left = 0, Top = 0, Right = screenWidth, Bottom = screenHeight };
            for (int i = 0; i < buf.Length; ++i)
            {
                buf[i].Attributes = 6;
                buf[i].Char.UnicodeChar = '☺';
            }
            bool b = WriteConsoleOutputW(
                fileHandle,
                buf,
                new Coord() { X = screenWidth, Y = screenHeight },
                new Coord() { X = 0, Y = 0 },
                ref rect
            );
            Console.SetCursorPosition(0, 0);
        }
    }
}

我似乎已经排除了 CharSetA/W DLLImport 后缀、代码页控制台的所有组合strong> 属性和 源文件 编码。

(当然,将彩色笑脸字符快速打印到 C# 控制台是不可能的。有人告诉我,我在这里错过了一些愚蠢的东西;我花了大约 2 个小时谷歌搜索并尝试轻松模仿 1984 年管理的 Castle Adventure。)

我怎样才能让前面提到的 '☺' 打印除 '?' 以外的任何内容?还是':'?

【问题讨论】:

  • Console.OutputEncoding = System.Text.Encoding.UTF8;
  • @Mikael 遗憾的是,这对我来说并没有任何改变——无论是设置为 Unicode 还是 UTF8,它都会打印一个充满“:”的屏幕
  • 有趣。我在 Visual Studio 中加载了一个新的控制台应用程序,它为我打印了笑脸
  • Console.Write 没有问题 - 但使用 WriteConsoleOutput(为了控制每个字符的颜色)似乎在某种程度上忽略了这些编码设置。
  • stackoverflow.com/questions/2743260/… github.com/silkfire/Pastel

标签: c# unicode console


【解决方案1】:

这似乎与Using WriteConsoleOutput to write Unicode with c# 重复

解决方案是将CharSet = CharSet.Unicode 属性添加到CharInfoCharUnion 结构中。

【讨论】:

  • 是的,我还没有意识到这些参数的重要性——这确实解决了问题。谢谢:3
猜你喜欢
  • 2020-11-09
  • 2021-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-20
相关资源
最近更新 更多