Fork me on GitHub

颜色扩展类--ColorExtensions

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

 

posted @ 2017-07-25 11:56  VAllen  阅读(853)  评论(0编辑  收藏  举报