向控制台输出添加文本修饰

发布于 2024-10-20 22:11:05 字数 252 浏览 1 评论 0原文

我有 ac# .net 3.5 应用程序,它使用 StreamWriter 将文本写入控制台。有没有办法向打印到控制台的文本添加下划线和删除线等文本装饰?可能使用 ANSI 转义序列?

TextWriter writer = new StreamWriter(Console.OpenStandardOutput());
writer.WriteLine("some underlined text");

谢谢, 保罗·H

I have a c# .net 3.5 application that writes text to the console using a StreamWriter. Is there a way I can add text decorations like underline and strikethrough to the text that is printed to the console? Possibly using ANSI escape sequences?

TextWriter writer = new StreamWriter(Console.OpenStandardOutput());
writer.WriteLine("some underlined text");

Thanks,
PaulH

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

把时间冻结 2024-10-27 22:11:05

在 Windows 10 内部版本 16257 及更高版本中:

using System;
using System.Runtime.InteropServices;

class Program
{
    const int STD_OUTPUT_HANDLE = -11;
    const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;

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

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

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

    static void Main()
    {
        var handle = GetStdHandle(STD_OUTPUT_HANDLE);
        uint mode;
        GetConsoleMode(handle, out mode);
        mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        SetConsoleMode(handle, mode);

        const string UNDERLINE = "\x1B[4m";
        const string RESET = "\x1B[0m";
        Console.WriteLine("Some " + UNDERLINE + "underlined" + RESET + " text");
    }
}

带有下划线文本的控制台

In Windows 10 build 16257 and later:

using System;
using System.Runtime.InteropServices;

class Program
{
    const int STD_OUTPUT_HANDLE = -11;
    const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;

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

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

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

    static void Main()
    {
        var handle = GetStdHandle(STD_OUTPUT_HANDLE);
        uint mode;
        GetConsoleMode(handle, out mode);
        mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        SetConsoleMode(handle, mode);

        const string UNDERLINE = "\x1B[4m";
        const string RESET = "\x1B[0m";
        Console.WriteLine("Some " + UNDERLINE + "underlined" + RESET + " text");
    }
}

Console with underlined text

ら栖息 2024-10-27 22:11:05

我用这个代码。这是 Vladimir Reshetnikov 答案的固定版本,使用正确的转义码进行重置。

    private static void WriteUnderline(string s)
    {
        var handle = GetStdHandle(STD_OUTPUT_HANDLE);
        uint mode;
        GetConsoleMode(handle, out mode);
        mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        SetConsoleMode(handle, mode);
        Console.WriteLine($"\x1B[4m{s}\x1B[24m");
    }

这将执行带下划线的文本,并且具有不重置您设置的任何颜色的优点。

I use this code. It's a fixed version of Vladimir Reshetnikov's answer, using the correct escape code for the reset.

    private static void WriteUnderline(string s)
    {
        var handle = GetStdHandle(STD_OUTPUT_HANDLE);
        uint mode;
        GetConsoleMode(handle, out mode);
        mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        SetConsoleMode(handle, mode);
        Console.WriteLine($"\x1B[4m{s}\x1B[24m");
    }

This will do underlined text, and has the benefit of not resetting any colors you have set.

凉风有信 2024-10-27 22:11:05

Windows 控制台不支持 ANSI 转义序列。据我所知,更改输出字符属性的唯一方法是在写入字符之前调用SetConsoleTextAttribute。或者,在 .NET 中,修改 Console.ForegroundColorConsole.BackgroundColor 属性。

可以通过类型转换将这些属性设置为自定义值(即不是由 ConsoleColor 定义的值)。但我不知道这对你有什么好处。

我不知道我在 Windows 控制台上见过带删除线的文本,而且我已经很多年没有看到下划线了。我想这是可能的,但我不知道它是如何做到的。

The Windows console does not support ANSI escape sequences. To my knowledge, the only way to change the attributes of an output character is to call SetConsoleTextAttribute before writing the character. Or, in .NET, modify the Console.ForegroundColor or Console.BackgroundColor attributes.

It might be possible to set those properties to custom values (i.e. values not defined by ConsoleColor) with a type cast. But I don't know what good that would do you.

I don't know that I've ever seen strikethrough text on a Windows console, and it's been years since I saw underline. I suppose it's possible, but I don't know how it's done.

我家小可爱 2024-10-27 22:11:05

简短的回答,不;控制台不允许在输出中使用下划线字符。

更长的答案:控制台使用的屏幕缓冲区只不过是一个字节数组。每个光标位置都是一个字节或一个字符。要创建下划线,您需要两个字符重叠(这在控制台中是不可能的),或者您需要访问使用上部 128 个字符值作为下部 128 个字符值的下划线或删除线版本的代码页(我不知道一个)。

如果您愿意对带有下划线的行使用“双倍行距”,则可以解决此问题。字符代码 0x00AF(十进制 175)是一个“文本艺术”字符,表示字符空间顶部的边框。如果您在文本下方的行中使用这些内容,则会出现下划线。

Short answer, no; the console doesn't allow the use of underlined characters in output.

Longer answer: The screen buffer used by the console is little more than a byte array. Each cursor position is one byte or one character. To create an underline, you either need two characters overlapping (which isn't possible in the console), or you need access to a codepage that uses the upper 128 character values as underlined or strikethrough versions of the lower 128 (I don't know of one).

You can work around this if you are willing to go "double-spaced" for lines that have underlines. Character code 0x00AF (decimal 175) is a "text art" character representing a border across the top of the character space. If you use those in the line underneath your text, presto, underlines.

捂风挽笑 2024-10-27 22:11:05

我发现了这个问题,并想我应该使用 kernel32 函数添加到 Windows 10 之前的终端的答案中,

using System;
using System.Runtime.InteropServices;

namespace color_console
{
    class Class1
    {
        static void Main(string[] args)
        {
            Class1 c = new Class1();
            c.change();
        }

        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, CharacterAttributes wAttributes);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetStdHandle(int nStdHandle);

        [DllImport("kernel32.dll")]
        public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput,
                ref CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);


        void change()
        {
            const int STD_OUTPUT_HANDLE = -11;
            IntPtr hOut;
            hOut = GetStdHandle(STD_OUTPUT_HANDLE);

            CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo = new CONSOLE_SCREEN_BUFFER_INFO();
            GetConsoleScreenBufferInfo(hOut, ref ConsoleInfo);
            CharacterAttributes originalAttributes = (CharacterAttributes)ConsoleInfo.wAttributes;

            //write some text
            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_BLUE);
            Console.WriteLine("Blue text");

            SetConsoleTextAttribute(hOut, CharacterAttributes.BACKGROUND_RED);
            Console.WriteLine("Red background");

            SetConsoleTextAttribute(hOut, CharacterAttributes.BACKGROUND_GREEN);
            Console.WriteLine("Green background");

            SetConsoleTextAttribute(hOut, CharacterAttributes.BACKGROUND_GREEN | CharacterAttributes.BACKGROUND_RED);
            Console.WriteLine("Yellow background");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_RED | CharacterAttributes.COMMON_LVB_UNDERSCORE);
            Console.WriteLine("Red underlined text");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_RED
                                   | CharacterAttributes.FOREGROUND_BLUE);
            Console.WriteLine("Purple text");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_RED
                                    | CharacterAttributes.FOREGROUND_BLUE
                                    | CharacterAttributes.FOREGROUND_INTENSITY);
            Console.WriteLine("Purple text intense");
           
            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_GREEN
                                    | CharacterAttributes.FOREGROUND_BLUE
                                    | CharacterAttributes.COMMON_LVB_REVERSE_VIDEO);
            Console.WriteLine("Aqua reversed text ");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_GREEN
                                    | CharacterAttributes.FOREGROUND_BLUE
                                    | CharacterAttributes.COMMON_LVB_REVERSE_VIDEO
                                    | CharacterAttributes.FOREGROUND_INTENSITY);
            Console.WriteLine("Aqua reversed intense text ");

            SetConsoleTextAttribute(hOut, CharacterAttributes.COMMON_LVB_GRID_LVERTICAL
                                    | CharacterAttributes.FOREGROUND_GREEN);
            Console.WriteLine("What does this do");

            SetConsoleTextAttribute(hOut, originalAttributes);
            Console.WriteLine("Back to the shire");
        }

        public enum CharacterAttributes
        {
            FOREGROUND_BLUE =   0x0001,
            FOREGROUND_GREEN =  0x0002,
            FOREGROUND_RED =    0x0004,
            FOREGROUND_INTENSITY = 0x0008,
            BACKGROUND_BLUE = 0x0010,
            BACKGROUND_GREEN = 0x0020,
            BACKGROUND_RED = 0x0040,
            BACKGROUND_INTENSITY = 0x0080,
            COMMON_LVB_LEADING_BYTE = 0x0100,
            COMMON_LVB_TRAILING_BYTE = 0x0200,
            COMMON_LVB_GRID_HORIZONTAL = 0x0400,
            COMMON_LVB_GRID_LVERTICAL = 0x0800,
            COMMON_LVB_GRID_RVERTICAL = 0x1000,
            COMMON_LVB_REVERSE_VIDEO = 0x4000,
            COMMON_LVB_UNDERSCORE = 0x8000
        }

 

        [StructLayout(LayoutKind.Sequential)]
        public struct CONSOLE_SCREEN_BUFFER_INFO
        {
            public COORD dwSize;
            public COORD dwCursorPosition;
            public int wAttributes;
            public SMALL_RECT srWindow;
            public COORD dwMaximumWindowSize;
        }

 

        // Standard structures used for interop with kernel32
        [StructLayout(LayoutKind.Sequential)]
        public struct COORD
        {
            public short x;
            public short y;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SMALL_RECT

        {
            public short Left;
            public short Top;
            public short Right;
            public short Bottom;
        }
    }
}

在我的 PC 上输出

在此处输入图像描述

I found this question and thought I would add to the answers for pre-windows 10 terminal using kernel32 functions,

using System;
using System.Runtime.InteropServices;

namespace color_console
{
    class Class1
    {
        static void Main(string[] args)
        {
            Class1 c = new Class1();
            c.change();
        }

        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, CharacterAttributes wAttributes);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetStdHandle(int nStdHandle);

        [DllImport("kernel32.dll")]
        public static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput,
                ref CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);


        void change()
        {
            const int STD_OUTPUT_HANDLE = -11;
            IntPtr hOut;
            hOut = GetStdHandle(STD_OUTPUT_HANDLE);

            CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo = new CONSOLE_SCREEN_BUFFER_INFO();
            GetConsoleScreenBufferInfo(hOut, ref ConsoleInfo);
            CharacterAttributes originalAttributes = (CharacterAttributes)ConsoleInfo.wAttributes;

            //write some text
            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_BLUE);
            Console.WriteLine("Blue text");

            SetConsoleTextAttribute(hOut, CharacterAttributes.BACKGROUND_RED);
            Console.WriteLine("Red background");

            SetConsoleTextAttribute(hOut, CharacterAttributes.BACKGROUND_GREEN);
            Console.WriteLine("Green background");

            SetConsoleTextAttribute(hOut, CharacterAttributes.BACKGROUND_GREEN | CharacterAttributes.BACKGROUND_RED);
            Console.WriteLine("Yellow background");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_RED | CharacterAttributes.COMMON_LVB_UNDERSCORE);
            Console.WriteLine("Red underlined text");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_RED
                                   | CharacterAttributes.FOREGROUND_BLUE);
            Console.WriteLine("Purple text");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_RED
                                    | CharacterAttributes.FOREGROUND_BLUE
                                    | CharacterAttributes.FOREGROUND_INTENSITY);
            Console.WriteLine("Purple text intense");
           
            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_GREEN
                                    | CharacterAttributes.FOREGROUND_BLUE
                                    | CharacterAttributes.COMMON_LVB_REVERSE_VIDEO);
            Console.WriteLine("Aqua reversed text ");

            SetConsoleTextAttribute(hOut, CharacterAttributes.FOREGROUND_GREEN
                                    | CharacterAttributes.FOREGROUND_BLUE
                                    | CharacterAttributes.COMMON_LVB_REVERSE_VIDEO
                                    | CharacterAttributes.FOREGROUND_INTENSITY);
            Console.WriteLine("Aqua reversed intense text ");

            SetConsoleTextAttribute(hOut, CharacterAttributes.COMMON_LVB_GRID_LVERTICAL
                                    | CharacterAttributes.FOREGROUND_GREEN);
            Console.WriteLine("What does this do");

            SetConsoleTextAttribute(hOut, originalAttributes);
            Console.WriteLine("Back to the shire");
        }

        public enum CharacterAttributes
        {
            FOREGROUND_BLUE =   0x0001,
            FOREGROUND_GREEN =  0x0002,
            FOREGROUND_RED =    0x0004,
            FOREGROUND_INTENSITY = 0x0008,
            BACKGROUND_BLUE = 0x0010,
            BACKGROUND_GREEN = 0x0020,
            BACKGROUND_RED = 0x0040,
            BACKGROUND_INTENSITY = 0x0080,
            COMMON_LVB_LEADING_BYTE = 0x0100,
            COMMON_LVB_TRAILING_BYTE = 0x0200,
            COMMON_LVB_GRID_HORIZONTAL = 0x0400,
            COMMON_LVB_GRID_LVERTICAL = 0x0800,
            COMMON_LVB_GRID_RVERTICAL = 0x1000,
            COMMON_LVB_REVERSE_VIDEO = 0x4000,
            COMMON_LVB_UNDERSCORE = 0x8000
        }

 

        [StructLayout(LayoutKind.Sequential)]
        public struct CONSOLE_SCREEN_BUFFER_INFO
        {
            public COORD dwSize;
            public COORD dwCursorPosition;
            public int wAttributes;
            public SMALL_RECT srWindow;
            public COORD dwMaximumWindowSize;
        }

 

        // Standard structures used for interop with kernel32
        [StructLayout(LayoutKind.Sequential)]
        public struct COORD
        {
            public short x;
            public short y;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SMALL_RECT

        {
            public short Left;
            public short Top;
            public short Right;
            public short Bottom;
        }
    }
}

Output on my PC

enter image description here

分开我的手 2024-10-27 22:11:05

更改控制台的前景色/背景色非常容易: http://www.dotnetperls.com/console- color 但据我所知,例如,无法放置一些粗体文本。但我并没有真正尝试实现这一目标,所以我不确定。

It's pretty easy to change the foreground/background color of console : http://www.dotnetperls.com/console-color but AFAIK there is no way to put some bold text, for example. But I didn't really tried to achieve that so i'm not sure.

玩世 2024-10-27 22:11:05

对于未来的查看者来说,在更高的 .NET 版本中不再需要 API 调用。

.NET 4.8 中的以下内容按原样完美运行,无需 extern。

const string CLS ="\u001bc\x1b[3J";         //clear screen
const string RESET = "\x1B[0m";             //set format to default
const string BOLD = "\x1B[1m";              //bold text
const string DISABLED = "\x1B[2m";          //darkens, based on color
const string ITALICS = "\x1B[3m";           //italics text
const string UNDERLINE = "\x1B[4m";         //underline text
const string BLINK = "\x1B[5m";             //blinks from set color to darker set color.
const string INVERT = "\x1B[7m";            //inverts background with foreground.
const string STRIKE = "\x1B[9m";            //strikethrough the text
const string FGCOLOR = "\u001b[38;5;3m";    //38 - forground, 3m - yellow (256 color palette)
const string BGCOLOR = "\u001b[48;5;1m";    //48 - background, 1m - red (256 color palette)

Console.WriteLine($"{CLS}Demo: " +
                    $"{UNDERLINE}underlined{RESET}, " +
                    $"{FGCOLOR}{ITALICS}ITALICS{RESET}, " +
                    $"{FGCOLOR}{DISABLED}DISABLED{RESET}, " +
                    $"{BOLD}BOLD{RESET}, " +
                    $"{BLINK}BLINK{RESET}, " +
                    $"{FGCOLOR}FGCOLOR, " +
                    $"{INVERT}INVERT{RESET}, " +
                    $"{BGCOLOR}BGCOLOR, " +
                    $"{INVERT}INVERT{RESET}, " +
                    $"{STRIKE}STRIKE{RESET} " +
                    $"text.");

Just for future viewers, the API calls are not needed anymore under later .NET versions.

The following in .NET 4.8 works perfectly as is, no extern required.

const string CLS ="\u001bc\x1b[3J";         //clear screen
const string RESET = "\x1B[0m";             //set format to default
const string BOLD = "\x1B[1m";              //bold text
const string DISABLED = "\x1B[2m";          //darkens, based on color
const string ITALICS = "\x1B[3m";           //italics text
const string UNDERLINE = "\x1B[4m";         //underline text
const string BLINK = "\x1B[5m";             //blinks from set color to darker set color.
const string INVERT = "\x1B[7m";            //inverts background with foreground.
const string STRIKE = "\x1B[9m";            //strikethrough the text
const string FGCOLOR = "\u001b[38;5;3m";    //38 - forground, 3m - yellow (256 color palette)
const string BGCOLOR = "\u001b[48;5;1m";    //48 - background, 1m - red (256 color palette)

Console.WriteLine(
quot;{CLS}Demo: " +
                    
quot;{UNDERLINE}underlined{RESET}, " +
                    
quot;{FGCOLOR}{ITALICS}ITALICS{RESET}, " +
                    
quot;{FGCOLOR}{DISABLED}DISABLED{RESET}, " +
                    
quot;{BOLD}BOLD{RESET}, " +
                    
quot;{BLINK}BLINK{RESET}, " +
                    
quot;{FGCOLOR}FGCOLOR, " +
                    
quot;{INVERT}INVERT{RESET}, " +
                    
quot;{BGCOLOR}BGCOLOR, " +
                    
quot;{INVERT}INVERT{RESET}, " +
                    
quot;{STRIKE}STRIKE{RESET} " +
                    
quot;text.");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文