12

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

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

谢谢,保罗

4

6 回答 6

21

在 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");
    }
}

带有下划线文本的控制台

于 2017-03-28T19:52:23.477 回答
7

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

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

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

于 2011-03-08T20:29:45.257 回答
6

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

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

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

于 2011-03-08T20:27:22.593 回答
6

我使用此代码。这是 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");
    }

这将使用带下划线的文本,并且不会重置您设置的任何颜色。

于 2018-09-01T11:21:53.770 回答
1

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

于 2011-03-08T20:26:34.080 回答
1

我发现了这个问题,并认为我会使用 kernel32 函数添加到 pre-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;
        }
    }
}

在我的电脑上输出

于 2022-01-27T17:42:13.133 回答