/// <summary> /// 颜色扩展类 /// </summary> public static class ColorExtensions { /// <summary> /// .NET预定义的系统颜色缓存列表 /// </summary> private static readonly Dictionary<int, Color> ColorCache; /// <summary> /// 拥有相同颜色代码值的系统颜色名称列表 /// </summary> private static readonly Dictionary<int, string[]> DuplicateColorNameCache; /// <summary> /// 静态构造函数 /// </summary> static ColorExtensions() { ColorCache = new Dictionary<int, Color>(); DuplicateColorNameCache = new Dictionary<int, string[]>(); Type type = typeof(Color); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase); foreach (var propertyInfo in properties) { var value = propertyInfo.GetValue(null, null); if (value is Color) { var color = (Color) value; var intCode = color.ToIntCode(); if (!ColorCache.ContainsKey(intCode)) { ColorCache.Add(intCode, color); } else { if (DuplicateColorNameCache.ContainsKey(intCode)) { var values = DuplicateColorNameCache[intCode].ToList(); values.Add(color.Name); DuplicateColorNameCache[intCode] = values.ToArray(); } else { string[] values = { ColorCache[intCode].Name, color.Name }; DuplicateColorNameCache[intCode] = values; } } } } } /// <summary> /// 返回用十进制格式的颜色值,该值范围在0~16777215。 /// <para>例:0表示黑色,16777215表示白色。</para> /// </summary> /// <param name="color">Color对象</param> /// <returns>十进制格式的颜色值</returns> public static int ToIntCode(this Color color) { int c = color.R; c = c | color.G << 8; c = c | color.B << 16; return c; //以下代码等效 //先转成16进制值,再转成10进制值 //var hexCode = color.ToHexCode(false);//获取十六进制格式的颜色代码值 //int intCode = Convert.ToInt32(hexCode, 16);//获取十进制格式的颜色代码值 } /// <summary> /// 返回十六进制格式的颜色值。 /// <para>例:Color.Gray(灰色)返回#808080。Color.FromArgb(192,192,192) 返回#C0C0C0</para> /// </summary> /// <param name="color">Color对象</param> /// <param name="isAddPrefix">是否添加前缀"#", 默认为 true。</param> /// <returns>十六进制格式的颜色值</returns> public static string ToHexCode(this Color color, bool isAddPrefix = true) { return string.Format("{0}{1:X2}{2:X2}{3:X2}", isAddPrefix ? "#" : string.Empty, color.R, color.G, color.B); //下面这个方法,遇到.NET预定义的颜色对象,会返回颜色名称,而不是十六进制值。 //return ColorTranslator.ToHtml(color); } /// <summary> /// 返回HTML支持的颜色代码值,如果颜色已在HTML预定义,则返回颜色名称,否则返回十六进制格式表示的代码值。 /// <para>例:Color.Gray(灰色)返回Gray。Color.FromArgb(192,192,192) 返回#C0C0C0(银白色)</para> /// <para>例:这是因为HTML中已预定义该颜色代码值,所以HTML支持该颜色代码值所对应的名称值。</para> /// <para>.NET有三对预定义颜色的代码值是相同的,所以当传入以ARGB表示的颜色对象刚好在这三对预定义颜色范围,那么只会返回一对中的其中一个颜色名称。</para> /// <para>当你需要知道另外一个颜色名称,你可以通过</para> /// </summary> /// <param name="color">Color对象</param> /// <returns>如果颜色已在HTML预定义,则返回颜色的友好名称,否则返回十六进制格式表示的代码值</returns> public static string ToHtmlCode(this Color color) { int intCode = color.ToIntCode(); if (ColorCache.ContainsKey(intCode)) { return ColorTranslator.ToHtml(ColorCache[intCode]); } /* * 上面之所以要这样做,是因为当使用者传过来一个使用ARGB表示的Color对象。 * 经过以上处理后,下面可以顺利返回颜色的名称。 * 例: Color color1 = Color.Gray; //灰色 * Color color2 = Color.FromArgb(color1.A, color1.R, color1.G, color1.B); * color1.ToHtmlCode() 返回"Gray" * color2.ToHtmlCode() 返回"#808080". * 其实以上两个Color对象是相等的,这两个对象调用ToHtmlCode()扩展方法都应该返回同一个结果才是比较合理的。 */ return ColorTranslator.ToHtml(color); } /// <summary> /// 获取具有相同代码值的颜色名称数组,如果没有,则返回null。 /// </summary> /// <param name="color">Color对象</param> /// <returns>返回具有相同代码值的颜色名称数组,如果没有,则返回null。</returns> public static string[] GetDuplicateColorNames(this Color color) { int intCode = color.ToIntCode(); if (DuplicateColorNameCache.ContainsKey(intCode)) { return DuplicateColorNameCache[intCode]; } return null; } /// <summary> /// 转换十进制格式的颜色代码值为Color对象 /// </summary> /// <param name="intCode">十进制格式的颜色代码值</param> /// <returns>返回Color对象</returns> public static Color IntToColor(int intCode) { if (ColorCache.ContainsKey(intCode)) { return ColorCache[intCode]; } /* * 以上处理与ToHtmlCode方法同理 * 先检查是否与.NET预定义的颜色匹配,如果匹配,返回.NET预定义的颜色对象(该对象包含一个可被直接理解的颜色友好名称)。 * 如果不匹配,则返回用ARGB表示的Color对象。 */ string hexCode = Convert.ToString(intCode, 16); return ColorTranslator.FromHtml("#" + hexCode); } /// <summary> /// 转换以"#"开头的六位长度的十六进制格式的颜色代码值或.NET预定义的颜色名称为Color对象 /// </summary> /// <param name="hexCodeOrColorName">.NET预定义的颜色名称或以"#"开头的6位长度的十六进制颜色代码值</param> /// <returns></returns> public static Color HexOrNameToColor(string hexCodeOrColorName) { if (string.IsNullOrEmpty(hexCodeOrColorName)) { return Color.Empty; } try { //This is hex code. if (hexCodeOrColorName[0] == ‘#‘) { string hexCode = hexCodeOrColorName.Substring(1); int intCode = Convert.ToInt32(hexCode, 16); if (ColorCache.ContainsKey(intCode)) { //返回拥有友好名称的Color对象 return ColorCache[intCode]; } //返回以ARGB表示的Color对象 return ColorTranslator.FromHtml(hexCodeOrColorName); } //This is color name. return ColorTranslator.FromHtml(hexCodeOrColorName); } catch (Exception) { return Color.Empty; } } }
时间: 2024-11-06 22:04:05