本文告诉大家如何从字符串转颜色,从颜色转字符串
字符串转颜色
在 WPF 可以使用下面的代码把十六进制的颜色字符串转颜色
            Color color = (Color) ColorConverter.ConvertFromString("#FFDFD991");
string hex = "#FFFFFF";  
Color color = System.Drawing.ColorTranslator.FromHtml(hex); 
但是 UWP 没这个方法,所以需要自己写一个方法
        public SolidColorBrush GetSolidColorBrush(string hex)
        {
            hex = hex.Replace("#", string.Empty);
            byte a = (byte) (Convert.ToUInt32(hex.Substring(0, 2), 16));
            byte r = (byte) (Convert.ToUInt32(hex.Substring(2, 2), 16));
            byte g = (byte) (Convert.ToUInt32(hex.Substring(4, 2), 16));
            byte b = (byte) (Convert.ToUInt32(hex.Substring(6, 2), 16));
            return new SolidColorBrush(Windows.UI.Color.FromArgb(a, r, g, b));
        }
如果有小伙伴传入一个不带透明的,那么上面的代码就会出现异常,因为不带透明的颜色只有 6 个字符,所以就无法使用上面的代码,我修改了下面代码可以转换颜色
       public SolidColorBrush GetSolidColorBrush(string hex)
        {
            hex = hex.Replace("#", string.Empty);
            bool existAlpha = hex.Length == 8;
            if (!existAlpha && hex.Length != 6)
            {
                throw new ArgumentException("输入的hex不是有效颜色");
            }
            int n = 0;
            byte a;
            if (existAlpha)
            {
                n = 2;
                a = (byte) ConvertHexToByte(hex, 0);
            }
            else
            {
                a = 0xFF;
            }
            var r = (byte) ConvertHexToByte(hex, n);
            var g = (byte) ConvertHexToByte(hex, n + 2);
            var b = (byte) ConvertHexToByte(hex, n + 4);
            return new SolidColorBrush(Windows.UI.Color.FromArgb(a, r, g, b));
        }
        private static uint ConvertHexToByte(string hex, int n)
        {
            return Convert.ToUInt32(hex.Substring(n, 2), 16);
        }
大家可以从上面代码发现 ConvertHexToByte 这就是 16 进制转 int 的方法,请看C# 16 进制字符串转 int
但是存在这样写的颜色 #FD92 #DAC 的颜色,所以还需要继续修改一下算法
       public SolidColorBrush GetSolidColorBrush(string hex)
        {
            hex = hex.Replace("#", string.Empty);
            //#FFDFD991
            //#DFD991
            //#FD92
            //#DAC
            bool existAlpha = hex.Length == 8 || hex.Length == 4;
            bool isDoubleHex = hex.Length == 8 || hex.Length == 6;
            if (!existAlpha && hex.Length != 6 && hex.Length != 3)
            {
                throw new ArgumentException("输入的hex不是有效颜色");
            }
            int n = 0;
            byte a;
            int hexCount = isDoubleHex ? 2 : 1;
            if (existAlpha)
            {
                n = hexCount;
                a = (byte) ConvertHexToByte(hex, 0, hexCount);
                if (!isDoubleHex)
                {
                    a = (byte) (a * 16 + a);
                }
            }
            else
            {
                a = 0xFF;
            }
            var r = (byte) ConvertHexToByte(hex, n, hexCount);
            var g = (byte) ConvertHexToByte(hex, n + hexCount, hexCount);
            var b = (byte) ConvertHexToByte(hex, n + 2 * hexCount, hexCount);
            if (!isDoubleHex)
            {
                //#FD92 = #FFDD9922
                r = (byte) (r * 16 + r);
                g = (byte) (g * 16 + g);
                b = (byte) (b * 16 + b);
            }
            return new SolidColorBrush(Windows.UI.Color.FromArgb(a, r, g, b));
        }
        private static uint ConvertHexToByte(string hex, int n, int count = 2)
        {
            return Convert.ToUInt32(hex.Substring(n, count), 16);
        }
如果想看微软的转换,请看 https://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/Media/Parsers.cs
可以复制的源代码:
如果你没有在上面看到代码,请点击 https://gist.github.com/lindexi/36c5e223ff77cfb8adc4909dec1576b5
另外,如果有引用 WindowsCommunityToolkit 库,那么还有更简单的方法,就是通过 Microsoft.Toolkit.Uwp.Helpers.ColorHelper.ToColor 方法,这个方法提供了高性能的,很少的字符串分配的方法解析颜色,但是要求传入的颜色必须添加 # 开头
如何引用 WindowsCommunityToolkit 库?请通过 NuGet 安装 Microsoft.Toolkit.Uwp 库
另一个版本是尝试转换,也就是输入的字符串不符合预期的时候不会炸
    static class ColorTextConverter
    {
        public static (bool success, Color? color) TryConvertSolidColorBrush(string hexColorText)
        {
            if (!hexColorText.StartsWith("#"))
            {
                return (false, null);
            }
            var hex = hexColorText.Replace("#", string.Empty);
            // 可以采用的格式如下
            // #FFDFD991   8 个字符 存在 Alpha 通道
            // #DFD991     6 个字符
            // #FD92       4 个字符 存在 Alpha 通道
            // #DAC        3 个字符
            bool existAlpha = hex.Length == 8 || hex.Length == 4;
            bool isDoubleHex = hex.Length == 8 || hex.Length == 6;
            if (!existAlpha && hex.Length != 6 && hex.Length != 3)
            {
                return (false, null);
            }
            int n = 0;
            byte a;
            // 表示十六进制的字符数量,使用两个字符还是一个字符表示
            int hexCount = isDoubleHex ? 2 : 1;
            if (existAlpha)
            {
                n = hexCount;
                var convertHexToByteResult = ConvertHexToByte(hex, 0, hexCount);
                if (!convertHexToByteResult.success)
                {
                    return (false, null);
                }
                a = convertHexToByteResult.hexNumber;
                if (!isDoubleHex)
                {
                    a = (byte) (a * 16 + a);
                }
            }
            else
            {
                a = 0xFF;
            }
            var result = ConvertHexToByte(hex, n, hexCount);
            if (!result.success)
            {
                return (false, null);
            }
            var r = result.hexNumber;
            result = ConvertHexToByte(hex, n + hexCount, hexCount);
            if (!result.success)
            {
                return (false, null);
            }
            var g = result.hexNumber;
            result = ConvertHexToByte(hex, n + 2 * hexCount, hexCount);
            if (!result.success)
            {
                return (false, null);
            }
            var b = result.hexNumber;
            if (!isDoubleHex)
            {
                //#FD92 = #FFDD9922
                r = (byte) (r * 16 + r);
                g = (byte) (g * 16 + g);
                b = (byte) (b * 16 + b);
            }
            return (true, Color.FromArgb(a, r, g, b));
        }
        private static (bool success, byte hexNumber) ConvertHexToByte(string hex, int n, int count = 2)
        {
            var hexText = hex.Substring(n, count);
            if (byte.TryParse(hexText, NumberStyles.HexNumber, new NumberFormatInfo(), out var hexNumber))
            {
                return (true, hexNumber);
            }
            return (false, byte.MinValue);
        }
    }
以上都有使用 Substring 方法从而需要分配内存,下面提供一个无多余内存分配的方法
static (bool success, byte a, byte r, byte g, byte b) ConvertToColor(string input)
{
    bool startWithPoundSign = input.StartsWith('#');
    var colorStringLength = input.Length;
    if (startWithPoundSign) colorStringLength -= 1;
    int currentOffset = startWithPoundSign ? 1 : 0;
    // 可以采用的格式如下
    // #FFDFD991   8 个字符 存在 Alpha 通道
    // #DFD991     6 个字符
    // #FD92       4 个字符 存在 Alpha 通道
    // #DAC        3 个字符
    if (colorStringLength == 8
        || colorStringLength == 6
        || colorStringLength == 4
        || colorStringLength == 3)
    {
        bool success;
        byte result;
        byte a;
        int readCount;
        // #DFD991     6 个字符
        // #FFDFD991   8 个字符 存在 Alpha 通道
        //if (colorStringLength == 8 || colorStringLength == 6)
        if (colorStringLength > 5)
        {
            readCount = 2;
        }
        else
        {
            readCount = 1;
        }
        bool includeAlphaChannel = colorStringLength == 8 || colorStringLength == 4;
        if (includeAlphaChannel)
        {
            (success, result) = HexCharToNumber(input, currentOffset, readCount);
            if (!success) return default;
            a = result;
            currentOffset += readCount;
        }
        else
        {
            a = 0xFF;
        }
        (success, result) = HexCharToNumber(input, currentOffset, readCount);
        if (!success) return default;
        byte r = result;
        currentOffset += readCount;
        (success, result) = HexCharToNumber(input, currentOffset, readCount);
        if (!success) return default;
        byte g = result;
        currentOffset += readCount;
        (success, result) = HexCharToNumber(input, currentOffset, readCount);
        if (!success) return default;
        byte b = result;
        return (true, a, r, g, b);
    }
    return default;
}
static (bool success, byte result) HexCharToNumber(string input, int offset, int readCount)
{
    Debug.Assert(readCount == 1 || readCount == 2, "要求 readCount 只能是 1 或者 2 的值,这是框架限制,因此不做判断");
    byte result = 0;
    for (int i = 0; i < readCount; i++, offset++)
    {
        var c = input[offset];
        byte n;
        if (c >= '0' && c <= '9')
        {
            n = (byte)(c - '0');
        }
        else if (c >= 'a' && c <= 'f')
        {
            n = (byte)(c - 'a' + 10);
        }
        else if (c >= 'A' && c <= 'F')
        {
            n = (byte)(c - 'A' + 10);
        }
        else
        {
            return default;
        }
        result *= 16;
        result += n;
    }
    if (readCount == 1)
    {
        result = (byte)(result * 16 + result);
    }
    return (true, result);
}
颜色转字符串
如果需要从颜色转字符串是很简单
Color.ToString()
上面的代码就可以输出字符串

本文会经常更新,请阅读原文: https://blog.lindexi.com/post/win10-uwp-%E9%A2%9C%E8%89%B2%E8%BD%AC%E6%8D%A2.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
如果你想持续阅读我的最新博客,请点击 RSS 订阅,推荐使用RSS Stalker订阅博客,或者收藏我的博客导航
    
         本作品采用
    知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
    进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:
    https://blog.lindexi.com
    ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请
    与我联系
    。
    
    本作品采用
    知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议
    进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:
    https://blog.lindexi.com
    ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请
    与我联系
    。
无盈利,不卖课,做纯粹的技术博客
以下是广告时间
        推荐关注 Edi.Wang 的公众号
        
        
    
        欢迎进入 Eleven 老师组建的 .NET 社区
        
         
    
以上广告全是友情推广,无盈利
 
             
    