将颜色转换为ConsoleColor?

时间:2010-01-01 15:07:33

标签: c# console colors system.drawing.color

System.Drawing.Color转换为类似System.ConsoleColor的最佳方法是什么?

8 个答案:

答案 0 :(得分:30)

以下是由.NET 4.5转换的控制台颜色十六进制值。首先是该计划:

using System;
using System.Drawing;

class Program
{
    static void Main(string[] args)
    {
        foreach (var n in Enum.GetNames(typeof(ConsoleColor)))
            Console.WriteLine("{0,-12} #{1:X6}", n, Color.FromName(n).ToArgb() & 0xFFFFFF);
    }
}

这是输出。正如您所看到的,DarkYellow的报告存在问题。该值的完整32位显示为零。所有其他人都有alpha通道的0xFF。

Black        #000000
DarkBlue     #00008B
DarkGreen    #006400
DarkCyan     #008B8B
DarkRed      #8B0000
DarkMagenta  #8B008B
DarkYellow   #000000   <-- see comments
Gray         #808080
DarkGray     #A9A9A9
Blue         #0000FF
Green        #008000
Cyan         #00FFFF
Red          #FF0000
Magenta      #FF00FF
Yellow       #FFFF00
White        #FFFFFF

编辑:我刚刚得到了更多的信息,所以这是一个从RGB到最近的ConsoleColor值的转换器。请注意,对System.Windows.Media的依赖仅适用于演示工具;实际函数本身只引用System.Drawing

using System;
using System.Windows.Media;

class NearestConsoleColor
{
    static ConsoleColor ClosestConsoleColor(byte r, byte g, byte b)
    {
        ConsoleColor ret = 0;
        double rr = r, gg = g, bb = b, delta = double.MaxValue;

        foreach (ConsoleColor cc in Enum.GetValues(typeof(ConsoleColor)))
        {
            var n = Enum.GetName(typeof(ConsoleColor), cc);
            var c = System.Drawing.Color.FromName(n == "DarkYellow" ? "Orange" : n); // bug fix
            var t = Math.Pow(c.R - rr, 2.0) + Math.Pow(c.G - gg, 2.0) + Math.Pow(c.B - bb, 2.0);
            if (t == 0.0)
                return cc;
            if (t < delta)
            {
                delta = t;
                ret = cc;
            }
        }
        return ret;
    }

    static void Main()
    {
        foreach (var pi in typeof(Colors).GetProperties())
        {
            var c = (Color)ColorConverter.ConvertFromString(pi.Name);
            var cc = ClosestConsoleColor(c.R, c.G, c.B);

            Console.ForegroundColor = cc;
            Console.WriteLine("{0,-20} {1} {2}", pi.Name, c, Enum.GetName(typeof(ConsoleColor), cc));
        }
    }
}

输出(部分)......

test output

答案 1 :(得分:22)

public static System.ConsoleColor FromColor(System.Drawing.Color c) {
    int index = (c.R > 128 | c.G > 128 | c.B > 128) ? 8 : 0; // Bright bit
    index |= (c.R > 64) ? 4 : 0; // Red bit
    index |= (c.G > 64) ? 2 : 0; // Green bit
    index |= (c.B > 64) ? 1 : 0; // Blue bit
    return (System.ConsoleColor)index;
}

ConsoleColors枚举似乎使用EGA样式调色板排序,即:

index Brgb
  0   0000  dark black
  1   0001  dark blue
  2   0010  dark green
  3   0011  dark cyan
  4   0100  dark red
  5   0101  dark purple
  6   0110  dark yellow (brown)
  7   0111  dark white (light grey)
  8   1000  bright black (dark grey)
  9   1001  bright blue
 10   1010  bright green
 11   1011  bright cyan    
 12   1100  bright red
 13   1101  bright purple
 14   1110  bright yellow
 15   1111  bright white

您可以将24位颜色(或32位颜色,通过忽略Alpha通道)粗略地映射到基本上具有亮度分量的3位颜色。在这种情况下,&#39;亮度&#39;如果任何System.Drawing.Color的红色,绿色或蓝色字节大于128,则设置位,如果等效源字节大于64,则设置红色,绿色,蓝色位。

答案 2 :(得分:14)

不幸的是,即使Windows控制台可以支持RGB颜色,Console类也只公开ConsoleColor枚举,这极大地限制了您可以使用的颜色。如果你想将Color结构映射到“最接近的”ConsoleColor,那将会非常棘手。

但是如果你想让命名的颜色与相应的ConsoleColor相匹配,你可以创建一个如下的地图:

var map = new Dictionary<Color, ConsoleColor>();
map[Color.Red] = ConsoleColor.Red;
map[Color.Blue] = ConsoleColor.Blue;
etc...

如果表现不那么重要,你可以通过String往返。 (仅适用于命名颜色

var color = Enum.Parse(typeof(ConsoleColor), color.Name);

编辑:这是指向question about finding color "closeness"的链接。

答案 3 :(得分:2)

在Vista上,稍后会看到SetConsoleScreenBufferInfoEx API函数。

有关用法的示例,请参阅另一个非常相似的StackOverflow问题的my answer。 (感谢Hans Passant的原始答案)。

答案 4 :(得分:2)

您可以使用反射。

public static class ColorHelpers
{
    public static bool TryGetConsoleColor(Color color, out ConsoleColor consoleColor)
    {
        foreach (PropertyInfo property in typeof (Color).GetProperties())
        {
            Color c = (Color) property.GetValue(null);

            if (color == c)
            {
                int index = Array.IndexOf(Enum.GetNames(typeof (ConsoleColor)), property.Name);
                if (index != -1)
                {
                    consoleColor = (ConsoleColor) Enum.GetValues(typeof (ConsoleColor)).GetValue(index);
                    return true;
                }
            }
        }
        consoleColor = default (ConsoleColor);
        return false;
    }
}

用法:

private static void Main()
{
    ConsoleColor c;
    if (ColorHelpers.TryGetConsoleColor(Color.Red, out c))
    {
        Console.ForegroundColor = c;
    }
}

答案 5 :(得分:1)

使用GetHue类的GetBrightnessGetSaturationColor方法可以实现简单有效的方法。

public static ConsoleColor GetConsoleColor(this Color color) {
    if (color.GetSaturation() < 0.5) {
        // we have a grayish color
        switch ((int)(color.GetBrightness()*3.5)) {
        case 0:  return ConsoleColor.Black;
        case 1:  return ConsoleColor.DarkGray;
        case 2:  return ConsoleColor.Gray;
        default: return ConsoleColor.White;
        }
    }
    int hue = (int)Math.Round(color.GetHue()/60, MidpointRounding.AwayFromZero);
    if (color.GetBrightness() < 0.4) {
        // dark color
        switch (hue) {
        case 1:  return ConsoleColor.DarkYellow;
        case 2:  return ConsoleColor.DarkGreen;
        case 3:  return ConsoleColor.DarkCyan;
        case 4:  return ConsoleColor.DarkBlue;
        case 5:  return ConsoleColor.DarkMagenta;
        default: return ConsoleColor.DarkRed;
        }
    }
    // bright color
    switch (hue) {
    case 1:  return ConsoleColor.Yellow;
    case 2:  return ConsoleColor.Green;
    case 3:  return ConsoleColor.Cyan;
    case 4:  return ConsoleColor.Blue;
    case 5:  return ConsoleColor.Magenta;
    default: return ConsoleColor.Red;
    }
}

请注意,控制台的颜色名称与众所周知的颜色不匹配。因此,如果你测试颜色映射方案,你必须记住(例如)众所周知的颜色,灰色是深灰色,浅灰色是灰色,绿色是深绿色,石灰是纯绿色,橄榄色是黑色黄色。

答案 6 :(得分:1)

轻松一个...

    $db = mysqli_connect('localhost', 'root', '', 'inventory');

    if (isset($_GET['sell'])) {
        $item_id = $_GET['sell'];
        $balance_query= mysqli_fetch_assoc(mysqli_query($db, "SELECT balance_quantity FROM item_master WHERE item_id=$item_id"));

$balance_quantity = balance_query['balance_quantity'];

//Rest of logic. Or even better, make a function that plain returns getBalance($itemId)

    }

答案 7 :(得分:0)

在版本6(以及任何ConsoleWindowClass窗口)之前,PowerShell.exe的默认默认“白底蓝色”颜色实际上是 DarkMagenta 上的 DarkYellow ,如果您选中了{ {1}}。这是因为$Host.UI.RawUI枚举值只是控制台颜色表的索引,它是可配置的(请参见this answer about DarkYellow)。

以下是默认控制台颜色表的十六进制RGB值:

ConsoleColor