24-Bit Console Color ANSI Codes in Cygwin

余生长醉 提交于 2021-01-27 18:07:24

问题


I wrote this simple C#/.NET Core console app code which outputs a set of color cubes of 7x7x7, testing 24-bit color rather than 256-color mode, as well as a custom TTF font I use that's derived from the "Ultimate Old School PC Font Pack" to include some extra Unicode block characters.

It works great in the Windows 10 terminal as seen, but tanks in Cygwin, even though it should be supported according to Github (https://gist.github.com/XVilka/8346728).

Any ideas on what could be wrong, if there's something in the code using [38m or [48m codes that might be somehow less compatible with Cygwin using either Cygwin.bat or mintty from Cygwin?

However, as you can see from the third picture it looks just fine in Mintty from Mingw64/MSYS2, but I would prefer to use Cygwin. It somehow mangles the triangle characters in the third picture as you can see, even when I set the character set setup as UTF-8 in mintty.

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();
        }
    }
}

Command Prompt:

Cygwin Command Prompt or Mintty 3.1.6 from Cygwin in Windows 10:

Mintty 3.1.6 in Mingw64 from MSYS2 in Windows 10:


回答1:


The following blog article shows what needs to be done. Apparently some win32 calls still need to be made in .NET Core console apps on Windows 10 for Cygwin/Mintty to work properly with them.

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

Code:

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;
    }
}

This line is of particular importance:

outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;


来源:https://stackoverflow.com/questions/62165191/24-bit-console-color-ansi-codes-in-cygwin

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!