将System.Drawing.Color
转换为类似System.ConsoleColor
的最佳方法是什么?
答案 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));
}
}
}
输出(部分)......
答案 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
类的GetBrightness
,GetSaturation
和Color
方法可以实现简单有效的方法。
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