【问题标题】:Custom text color in C# console application?C# 控制台应用程序中的自定义文本颜色?
【发布时间】:2014-09-06 15:05:59
【问题描述】:

我刚刚完成了一个项目的 C# 控制台应用程序代码,并想为我的字体添加一些颜色。我希望能够使用自定义颜色 - 橙色。有没有办法做到这一点?

这是我过去用来更改颜色的代码,但它不提供橙色:

Console.ForegroundColor = ConsoleColor.Magenta(and so on);

有没有办法为颜色或类似的东西插入一个十六进制值?

【问题讨论】:

标签: c# visual-studio console console-application textcolor


【解决方案1】:

http://msdn.microsoft.com/en-us/library/system.console.backgroundcolor.aspx找到的列表

我相信是控制台中唯一支持的颜色。不允许使用十六进制。

Black
DarkBlue
DarkGreen
DarkCyan
DarkRed
DarkMagenta
DarkYellow
Gray
DarkGray
Blue
Green
Cyan
Red
Magenta
Yellow
White

编辑

从我的公共仓库中获取工作项目文件

https://bitbucket.org/benskolnick/color-console/

但是在进一步的调查中,你可以做很多工作来结合红色和黄色来得到橙色。按照此处的示例进行操作。不会重新发布代码墙。 http://support.microsoft.com/kb/319883 这不会让您获得更多颜色,但会导致正确的方向。您将需要做一些 PINVOKE 工作,但我很容易将橙色或任何其他 RGB 颜色输入控制台。 http://pinvoke.net/default.aspx/kernel32.SetConsoleScreenBufferInfoEx

// Copyright Alex Shvedov
// Modified by MercuryP with color specifications
// Use this code in any way you want

using System;
using System.Diagnostics;                // for Debug
using System.Drawing;                    // for Color (add reference to  System.Drawing.assembly)
using System.Runtime.InteropServices;    // for StructLayout

class SetScreenColorsApp
{
    [StructLayout(LayoutKind.Sequential)]
    internal struct COORD
    {
        internal short X;
        internal short Y;
    }

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

    [StructLayout(LayoutKind.Sequential)]
    internal struct COLORREF
    {
        internal uint ColorDWORD;

        internal COLORREF(Color color)
        {
            ColorDWORD = (uint) color.R + (((uint) color.G) << 8) + (((uint) color.B) << 16);
        }

        internal COLORREF(uint r, uint g, uint b)
        {
            ColorDWORD = r + (g << 8) + (b << 16);
        }

        internal Color GetColor()
        {
            return Color.FromArgb((int) (0x000000FFU & ColorDWORD),
                                  (int) (0x0000FF00U & ColorDWORD) >> 8, (int) (0x00FF0000U & ColorDWORD) >> 16);
        }

        internal void SetColor(Color color)
        {
            ColorDWORD = (uint) color.R + (((uint) color.G) << 8) + (((uint) color.B) << 16);
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct CONSOLE_SCREEN_BUFFER_INFO_EX
    {
        internal int cbSize;
        internal COORD dwSize;
        internal COORD dwCursorPosition;
        internal ushort wAttributes;
        internal SMALL_RECT srWindow;
        internal COORD dwMaximumWindowSize;
        internal ushort wPopupAttributes;
        internal bool bFullscreenSupported;
        internal COLORREF black;
        internal COLORREF darkBlue;
        internal COLORREF darkGreen;
        internal COLORREF darkCyan;
        internal COLORREF darkRed;
        internal COLORREF darkMagenta;
        internal COLORREF darkYellow;
        internal COLORREF gray;
        internal COLORREF darkGray;
        internal COLORREF blue;
        internal COLORREF green;
        internal COLORREF cyan;
        internal COLORREF red;
        internal COLORREF magenta;
        internal COLORREF yellow;
        internal COLORREF white;
    }

    const int STD_OUTPUT_HANDLE = -11;                                        // per WinBase.h
    internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);    // per WinBase.h

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

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool GetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX csbe);

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetConsoleScreenBufferInfoEx(IntPtr hConsoleOutput, ref CONSOLE_SCREEN_BUFFER_INFO_EX csbe);

    // Set a specific console color to an RGB color
    // The default console colors used are gray (foreground) and black (background)
    public static int SetColor(ConsoleColor consoleColor, Color targetColor)
    {
        return SetColor(consoleColor, targetColor.R, targetColor.G, targetColor.B);
    }

    public static int SetColor(ConsoleColor color, uint r, uint g, uint b)
    {
        CONSOLE_SCREEN_BUFFER_INFO_EX csbe = new CONSOLE_SCREEN_BUFFER_INFO_EX();
        csbe.cbSize = (int)Marshal.SizeOf(csbe);                    // 96 = 0x60
        IntPtr hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);    // 7
        if (hConsoleOutput == INVALID_HANDLE_VALUE)
        {
            return Marshal.GetLastWin32Error();
        }
        bool brc = GetConsoleScreenBufferInfoEx(hConsoleOutput, ref csbe);
        if (!brc)
        {
            return Marshal.GetLastWin32Error();
        }

        switch (color)
        {
            case ConsoleColor.Black:
                csbe.black = new COLORREF(r, g, b);
                break;
            case ConsoleColor.DarkBlue:
                csbe.darkBlue = new COLORREF(r, g, b);
                break;
            case ConsoleColor.DarkGreen:
                csbe.darkGreen = new COLORREF(r, g, b);
                break;
            case ConsoleColor.DarkCyan:
                csbe.darkCyan = new COLORREF(r, g, b);
                break;
            case ConsoleColor.DarkRed:
                csbe.darkRed = new COLORREF(r, g, b);
                break;
            case ConsoleColor.DarkMagenta:
                csbe.darkMagenta = new COLORREF(r, g, b);
                break;
            case ConsoleColor.DarkYellow:
                csbe.darkYellow = new COLORREF(r, g, b);
                break;
            case ConsoleColor.Gray:
                csbe.gray = new COLORREF(r, g, b);
                break;
            case ConsoleColor.DarkGray:
                csbe.darkGray = new COLORREF(r, g, b);
                break;
            case ConsoleColor.Blue:
                csbe.blue = new COLORREF(r, g, b);
                break;
            case ConsoleColor.Green:
                csbe.green = new COLORREF(r, g, b);
                break;
            case ConsoleColor.Cyan:
                csbe.cyan = new COLORREF(r, g, b);
                break;
            case ConsoleColor.Red:
                csbe.red = new COLORREF(r, g, b);
                break;
            case ConsoleColor.Magenta:
                csbe.magenta = new COLORREF(r, g, b);
                break;
            case ConsoleColor.Yellow:
                csbe.yellow = new COLORREF(r, g, b);
                break;
            case ConsoleColor.White:
                csbe.white = new COLORREF(r, g, b);
                break;
        }
        ++csbe.srWindow.Bottom;
        ++csbe.srWindow.Right;
        brc = SetConsoleScreenBufferInfoEx(hConsoleOutput, ref csbe);
        if (!brc)
        {
            return Marshal.GetLastWin32Error();
        }
        return 0;
    }

    public static int SetScreenColors(Color foregroundColor, Color backgroundColor)
    {
        int irc;
        irc = SetColor(ConsoleColor.Gray, foregroundColor);
        if (irc != 0) return irc;
        irc = SetColor(ConsoleColor.Black, backgroundColor);
        if (irc != 0) return irc;

        return 0;
    }
}

如果你想使用橙色或任何其他颜色,你可以简单地调用 SetScreenColor

static void Main(string[] args)
    {

        Color screenTextColor = Color.Orange;
        Color screenBackgroundColor = Color.Black;
        int irc = SetScreenColorsApp.SetScreenColors(screenTextColor, screenBackgroundColor);
        Debug.Assert(irc == 0, "SetScreenColors failed, Win32Error code = " + irc + " = 0x" + irc.ToString("x"));

        Debug.WriteLine("LargestWindowHeight=" + Console.LargestWindowHeight + " LargestWindowWidth=" + Console.LargestWindowWidth);
        Debug.WriteLine("BufferHeight=" + Console.BufferHeight + " WindowHeight=" + Console.WindowHeight + " BufferWidth=" + Console.BufferWidth + " WindowWidth=" + Console.WindowWidth);
        //// these are relative to the buffer, not the screen:
        //Debug.WriteLine("WindowTop=" + Console.WindowTop + " WindowLeft=" + Console.WindowLeft);
        Debug.WriteLine("ForegroundColor=" + Console.ForegroundColor + " BackgroundColor=" + Console.BackgroundColor);
        Console.WriteLine("Some text in a console window");
        Console.BackgroundColor = ConsoleColor.Cyan;
        Console.ForegroundColor = ConsoleColor.Yellow;
        Debug.WriteLine("ForegroundColor=" + Console.ForegroundColor + " BackgroundColor=" + Console.BackgroundColor);
        Console.Write("Press ENTER to exit...");
        Console.ReadLine();

        // Note: If you use SetScreenColors, the RGB values of gray and black are changed permanently for the console window.
        // Using i.e. Console.ForegroundColor = ConsoleColor.Gray afterwards will switch the color to whatever you changed gray to

        // It's best to use SetColor for the purpose of choosing the 16 colors you want the console to be able to display, then use
        // Console.BackgroundColor and Console.ForegrondColor to choose among them.
    }

【讨论】:

  • 是的,我知道那些我希望有另一种方法来实现自定义颜色。奇怪的是,他们有 DarkMagenta 等,但没有橙色(我们学校的颜色是黑色和橙色)无论如何感谢您的帮助!
  • .Net 框架不支持控制台前景色的自定义 RGB 颜色很奇怪,因为它是本机支持的,所以看起来。伟大的解决方案本杰明!
  • 我尝试编译此代码,但收到错误消息:“附加信息:无法在 DLL 'kernel32.dll' 中找到名为 'GetConsoleScreenBufferInfoEx' 的入口点。”这一行似乎是问题所在: bool brc = GetConsoleScreenBufferInfoEx(hConsoleOutput, ref csbe);
  • "在 Vista 和更高版本上,请参阅 SetConsoleScreenBufferInfoEx API 函数。" stackoverflow.com/a/11188428/839573我正在使用 Windows XP... XP 有什么解决方法吗?
【解决方案2】:

自 Windows 10 周年更新以来,控制台可以使用 ANSI/VT100 颜色代码

  1. 您需要通过 SetConsoleMode 设置标志 ENABLE_VIRTUAL_TERMINAL_PROCESSING(0x4)
  2. 使用序列:

    "\x1b[48;5;" + s + "m" - 通过表中的索引设置背景颜色 (0-255)

    "\x1b[38;5;" + s + "m" - 通过表中的索引(0-255)设置前景色

    "\x1b[48;2;" + r + ";" + g + ";" + b + "m" - 通过 r,g,b 值设置背景

    "\x1b[38;2;" + r + ";" + g + ";" + b + "m" - 通过 r,g,b 值设置前景

重要提示:Windows 内部在表格中只有 256 种(或 88 种)颜色,Windows 将使用最接近表格中的 (r,g,b) 值。

示例代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        [DllImport( "kernel32.dll", SetLastError = true )]
        public static extern bool SetConsoleMode( IntPtr hConsoleHandle, int mode );
        [DllImport( "kernel32.dll", SetLastError = true )]
        public static extern bool GetConsoleMode( IntPtr handle, out int mode );

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

        static void Main( string[] args )
        {
            var handle = GetStdHandle( -11 );
            int mode;
            GetConsoleMode( handle, out mode );
            SetConsoleMode( handle, mode | 0x4 );

            for (int i=0;i<255;i++ )
            {
                Console.Write( "\x1b[48;5;" + i + "m*" );
            }

            Console.ReadLine();
        }
    }
}

结果:

Read about it in MSDN: Article 'Console Virtual Terminal Sequences'

【讨论】:

    【解决方案3】:

    在这里扩展 Alexei Shcherbakov Windows 10 ENABLE_VIRTUAL_TERMINAL_PROCESSING 的答案是一个完整的颜色代码映射,因此您可以将所有颜色及其各自的数字放在一个地方:

    【讨论】:

      【解决方案4】:

      迟到总比没有好,但现在看来这是可能的,至少在 Vista 和更高版本上是这样。因此,我将添加此内容以供有相同问题的其他人将来参考。

      当我打算这样做时,我遇到了 Hans Passant 的reply on MSDN

      我现在无法访问 Vista,所以无法尝试。但是有些东西 这样应该可以工作:

      CONSOLE_SCREEN_BUFFER_INFOEX info;
      info.cbSize = sizeof(info);
      HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
      GetConsoleScreenBufferInfoEx(hConsole, &info);
      info.ColorTable[14] = RGB(255, 128, 0);  // Replace yellow
      SetConsoleScreenBufferInfoEx(hConsole, &info);
      SetConsoleTextAttribute(hConsole, FOREGROUNDINTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
      

      这需要一点 p-Invoking,但应该会给你一些东西。

      【讨论】:

      【解决方案5】:

      您可以使用Colorful.Console,它可以让您使用自定义颜色,甚至可以使用 Figlet 字体来制作 ASCII 艺术!

      【讨论】:

        【解决方案6】:

        它不是橙色,因为该颜色不是控制台支持的颜色之一。我的意思是,即使使用 Windows API,您也无法获得它。如果您想验证它,请查看以下代码:

           public static class Win32
            {
                [DllImport("kernel32.dll", SetLastError = true)]
                public static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, short attributes);
        
                [DllImport("kernel32.dll", SetLastError = true)]
                public static extern IntPtr GetStdHandle(int nStdHandle);
            }
        
            public class Program
            {
                static void Main(string[] args)
                {
                    foreach(var i in Enumerable.Range(0, 100)) // why "100"? it is just any number
                    {
                        Win32.SetConsoleTextAttribute(Win32.GetStdHandle(-11), (short)i);
                        Console.WriteLine("Hello");
                    }
                }
            }
        

        【讨论】:

        • 我之前的答案有缺陷,因为它不允许您覆盖 16 种预定义颜色,我在 pinvoke.net 上找到了真正的答案,并在下面用代码墙更新了我的答案。 pinvoke.net/default.aspx/kernel32.SetConsoleScreenBufferInfoEx
        • 16 色限制是早年使用的 VGA 控制台的倒退(不是早年你只有单色的方式。:))
        【解决方案7】:

        进一步证明这不起作用(使用本杰明链接中的方法):

        using System.Runtime.InteropServices;
        
        namespace
        {
            class Program
            {
                [DllImport("kernel32.dll")]
                public static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, int wAttributes);
                [DllImport("kernel32.dll")]
                public static extern IntPtr GetStdHandle(uint nStdHandle);
        
                static void Main(string[] args)
                {
                    uint STD_OUTPUT_HANDLE = 0xfffffff5;
                    IntPtr hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        
                    SetConsoleTextAttribute(hConsole, (int)Colour.Red + (int)Colour.Green + (int)Colour.Intensity);
                    Console.WriteLine("Red + Green + Intensity == Yellow");
        
                    SetConsoleTextAttribute(hConsole, (int)Colour.Red + (int)Colour.Green + (int)Colour.Intensity + (int)Colour.Red);
                    Console.WriteLine("Yellow + Red != Orange");
        
                    SetConsoleTextAttribute(hConsole, 15);
                    Console.WriteLine();
                    Console.WriteLine("Press Enter to exit ...");
                    Console.Read();
                }
        
                public enum Colour
                {
                    Blue = 0x00000001,
                    Green = 0x00000002,
                    Red = 0x00000004,
                    Intensity = 0x00000008
                }
            }
        }
        

        此方法不允许您添加任何无法通过 ConsoleColor 访问的内容。真的很遗憾,因为我也很想在我的应用程序中添加橙色。如果有人找到了我会非常感兴趣的方法。

        【讨论】:

        • 我之前的答案有缺陷,因为它不允许您覆盖 16 种预定义颜色,我在 pinvoke.net 上找到了真正的答案,并在下面用代码墙更新了我的答案。 pinvoke.net/default.aspx/kernel32.SetConsoleScreenBufferInfoEx
        • 您的enum Colour 是位掩码,应该ORed 在一起,而不是ADDed 在一起。这就是为什么您只能获得原始的 16 种 VGA 颜色。 4+4=8(或红色+红色=强度)。
        【解决方案8】:

        有点晚了,我知道。但是,实现 C# 控制台中通常不可用的颜色的一种方法是更改​​注册表中颜色的 ColorCode。但请注意,这可能是最不可接受的方式。 只需打开regedit(Win + R,然后键入“regedit”),转到HKEY_CURRENT_USER,打开“Console”键(此时您应该导出“Console”键以便稍后恢复它)。在那里,您将看到从 ColorTable00 到 ColoTable15 的值列表。如果您将 ColorTable10 从 0x0000ff00 更改为 0x0000a5ff(或 65280 至 42495),则在重新启动后在控制台中使用 ConsoleColor.Green 时,您将看到橙色。也可以通过代码改变这个值

        using System;
        using Microsoft.Win32;
        
        namespace colorChanger
        {
            class Program
            {
                static void Main(string[] args)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Hello World");
                    RegistryKey regKey = Registry.CurrentUser.CreateSubKey("Console");
                    regKey.SetValue("ColorTable10", 42495, RegistryValueKind.DWord);
                    Console.ReadKey();
                }
            }
        }
        

        当然,这适用于所有其他 ColorTable-Values 和 Colorcodes,但它仅针对您 PC 上的用户进行更改。

        【讨论】:

          猜你喜欢
          • 2016-02-24
          • 2014-01-03
          • 1970-01-01
          • 2012-03-19
          • 2020-01-18
          • 2013-01-26
          • 1970-01-01
          相关资源
          最近更新 更多