将颜色转换为ConsoleColor?

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

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

但是,如果您希望命名的Color与相应的ConsoleColor匹配,您可以创建一个映射,例如:

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

或者如果性能不那么重要,您可以通过String进行往返。 (仅适用于指定颜色

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

编辑:这是一个关于寻找颜色“亲近”的问题的链接。

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

 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(cR - rr, 2.0) + Math.Pow(cG - gg, 2.0) + Math.Pow(cB - 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(cR, cG, cB); Console.ForegroundColor = cc; Console.WriteLine("{0,-20} {1} {2}", pi.Name, c, Enum.GetName(typeof(ConsoleColor), cc)); } } } 

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

测试输出

 public static System.ConsoleColor FromColor(System.Drawing.Color c) { int index = (cR > 128 | cG > 128 | cB > 128) ? 8 : 0; // Bright bit index |= (cR > 64) ? 4 : 0; // Red bit index |= (cG > 64) ? 2 : 0; // Green bit index |= (cB > 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位颜色。 在这种情况下,如果System.Drawing.Color中的任何一个红色,绿色或蓝色字节大于128,则设置’brightness’位;如果等效源字节大于64,则设置红色,绿色,蓝色位。

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

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

你可以使用reflection。

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

通过使用Color类的GetHueGetBrightnessGetSaturation方法,可以实现一种简单有效的方法。

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

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

容易一个……

公共共享函数ColorToConsoleColor(cColor As Color)作为ConsoleColor Dim cc作为ConsoleColor如果不是System.Enum.TryParse(Of ConsoleColor)(cColor.Name,cc)那么Dim intensity = If(Color.Gray.GetBrightness() =&H80,4,0)Dim g = If(cColor.G> =&H80,2,0)Dim b = If(cColor.B> =&H80 ,1,0)

  cc = CType(intensity + r + g + b, ConsoleColor) End If Return cc End Function