Cygwin 中的 24 位控制台颜色 ANSI 代码

24-Bit Console Color ANSI Codes in Cygwin

我编写了这个简单的 C#/.NET Core 控制台应用程序代码,它输出一组 7x7x7 的颜色立方体,测试 24 位颜色而不是 256 色模式,以及我使用的自定义 TTF 字体派生从 "Ultimate Old School PC Font Pack" 开始包含一些额外的 Unicode 块字符。

如所见,它在 Windows 10 终端中运行良好,但在 Cygwin 中运行不佳,尽管根据 Github (https://gist.github.com/XVilka/8346728).

如果代码中使用 [38m 或 [48m 代码可能与使用 Cygwin.bat 或来自 Cygwin 的 mintty 的 Cygwin 不太兼容,有什么可能出错的想法吗?

但是,正如您从第三张图片中看到的那样,它在 Mingw64/MSYS2 的 Mintty 中看起来还不错,但我更愿意使用 Cygwin。如您所见,它以某种方式破坏了第三张图片中的三角形字符,即使我在 mintty 中将字符集设置设置为 UTF-8。

using System;
using System.Text;

namespace ConsoleColor
{
    public class App
    {
        //int[] colorMeta1 = { 0, 85, 170, 255 };
        int[] colorMeta2 = { 0, 43, 85, 127, 170, 213, 255 };

        public App()
        {
            int length = colorMeta2.Length;
            int index = 0;
            Encoding defaultEncoder = Console.OutputEncoding;
            Console.OutputEncoding = Encoding.UTF8;
            for (int r=0;r<length;r++)
            {
                for(int g=0;g<length;g++)
                {
                    for(int b=0;b<length;b++)
                    {
                        int r2 = colorMeta2[r];
                        int g2 = colorMeta2[g];
                        int b2 = colorMeta2[b];
                        int foregroundColor = (r2 == 255 || g2 == 255 || b2 == 255) ? 0 : 255;
                        Console.Write($"\u001b[38;2;{r2};{g2};{b2}m█");
                        Console.Write($"\u001b[38;2;{foregroundColor};{foregroundColor};{foregroundColor}m\u001b[48;2;{r2};{g2};{b2}m({r2.ToString().PadLeft(3, ' ')},{g2.ToString().PadLeft(3, ' ')},{b2.ToString().PadLeft(3, ' ')})");
                        Console.Write($"\u001b[38;2;{r2};{g2};{b2}m█");
                        Console.Write($"\u001b[38;2;{170};{170};{170}m");
                        Console.Write($"\u001b[48;2;{0};{0};{0}m");
                        index++;
                    }
                    Console.WriteLine();
                }
            }
            Console.WriteLine($"{index} total colors.");
            for (int a = 0x2580; a <= 0x259F; a++)
                Console.Write($"{(char)a}");
            for (int a = 0x25E2; a <= 0x25E5; a++)
                Console.Write($"{(char)a}");
            Console.WriteLine();
            Console.OutputEncoding = defaultEncoder;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            App app = new App();
        }
    }
}

命令提示符:

Windows10 中来自 Cygwin 的 Cygwin 命令提示符或 Mintty 3.1.6:

Mingw64 中的 Mintty 3.1.6 来自 Windows10 中的 MSYS2:

以下博客文章显示了需要完成的工作。显然,某些 win32 调用仍需要在 Windows 10 上的 .NET Core 控制台应用程序中进行,以便 Cygwin/Mintty 与它们正常工作。

https://www.jerriepelser.com/blog/using-ansi-color-codes-in-net-console-apps/

代码:

private const int STD_OUTPUT_HANDLE = -11;
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
private const uint DISABLE_NEWLINE_AUTO_RETURN = 0x0008;

[DllImport("kernel32.dll")]
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

[DllImport("kernel32.dll")]
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);

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

[DllImport("kernel32.dll")]
public static extern uint GetLastError();

...

public void ConsoleInit()
{
    var iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (!GetConsoleMode(iStdOut, out uint outConsoleMode))
    {
        Console.WriteLine("failed to get output console mode");
        Console.ReadKey();
        return;
    }

    outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
    if (!SetConsoleMode(iStdOut, outConsoleMode))
    {
        Console.WriteLine($"failed to set output console mode, error code: {GetLastError()}");
        Console.ReadKey();
        return;
    }
}

这一行特别重要:

outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;