none
How to convert str "Color [Red]" into System.Drawing.Color = Color.Red RRS feed

  • Question

  • 
    How to convert the str "Color [Red] (saved as object and recovered as string) into System.Drawing.Color = Color.Red
    Monday, November 18, 2013 5:43 PM

Answers

  • Further to Reed's spanner in the works :P about unknown colours being written in an ARGB format, I put a panel on an empty form as something to change the colour of and used this code:

    Option Infer On Imports System.Text.RegularExpressions Public Class Form1 ''' <summary> ''' Convert a string of the format "color [nameOfColor]" or ''' "color [A=a, R=r, G=g, B=b]" to a System.Drawing.Color. ''' </summary> ''' <param name="s">The </param> ''' <returns>A a System.Drawing.Color.</returns> ''' <remarks>Falls back to fallbackColour if the colour could not be parsed.</remarks> Public Shared Function ColourFromData(s As String) As Color Dim fallbackColour = Color.Black If Not s.StartsWith("color", StringComparison.OrdinalIgnoreCase) Then Return fallbackColour End If ' Extract whatever is between the brackets. Dim re = New Regex("\[(.+?)]") Dim colorNameMatch = re.Match(s) If Not colorNameMatch.Success Then Return fallbackColour End If Dim colourName = colorNameMatch.Groups(1).Value ' Get the names of the known colours. 'TODO: If this function is called frequently, consider creating allColours as a variable with a larger scope. Dim allColours = [Enum].GetNames(GetType(System.Drawing.KnownColor)) ' Attempt a case-insensitive match to the known colours. Dim nameOfColour = allColours.FirstOrDefault(Function(c) String.Compare(c, colourName, StringComparison.OrdinalIgnoreCase) = 0) If Not String.IsNullOrEmpty(nameOfColour) Then Return Color.FromName(nameOfColour) End If ' Was not a named colour. Parse for ARGB values. re = New Regex("A=(\d+).*?R=(\d+).*?G=(\d+).*?B=(\d+)", RegexOptions.IgnoreCase) Dim componentMatches = re.Match(colourName) If componentMatches.Success Then Dim a = Integer.Parse(componentMatches.Groups(1).Value) Dim r = Integer.Parse(componentMatches.Groups(2).Value) Dim g = Integer.Parse(componentMatches.Groups(3).Value) Dim b = Integer.Parse(componentMatches.Groups(4).Value) Return System.Drawing.Color.FromArgb(a, r, g, b) End If Return fallbackColour End Function Private Sub SetBackgroundColour(c As Control, s As String) c.BackColor = ColourFromData(s) End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim testData = "color [A=99, R=99, G=19, B=255]" SetBackgroundColour(Panel1, testData) End Sub End Class


    HTH,

    Andrew

    Monday, November 18, 2013 9:06 PM
  • 
    How to convert the str "Color [Red] (saved as object and recovered as string) into System.Drawing.Color = Color.Red

    Well you can use Color.FromName where you use the name of the color and not Color.Red.

    Also color names are case specific so red would not work. If the recovered string is "Color.Red" then split the string at the decimal or period so the array contains Color and Red in index 0 and 1 consecutively.

    Then Color.FromName(SplitArray(1)) should work. In your instance you will need to get Red from between the brackets in the string if the string is "Color [Red]" which you can do with a variety of methods including Regex. If you find that too difficult to do then I will provide a couple of solutions that can do that if you need.

    Option Strict On
    
    Public Class Form1
    
        Dim MyColor As Color
        Dim Test As String = "Color.Red"
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            Dim SplitTest() As String
            SplitTest = Test.Split("."c)
            MyColor = Color.FromName(SplitTest(1))
            Me.BackColor = MyColor
            Me.Text = SplitTest(1)
        End Sub
    
    End Class



    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.



    Monday, November 18, 2013 6:57 PM
  • Yes Reed is absolutely correct. It does depend on what information is in your string since it could be a name if the color is a named color or it could be a hexadecimal value for a color or an ARGB value for a color or possibly something else that I am unfamiliar with.

    Note that in the color dialog in the image I placed the cursor in the blue area of the custom colors window as shown by the object that has two vertical and horizontal lines with the center of where they "meet" as the color of choice and then moved the left facing arrow on the right of the window up to the color I wanted which is displayed in the Color|Solid window before I pressed O.K.

    Option Strict On
    
    Public Class Form1
    
        Dim NewColor As Color = Color.Black ' Default color if user cancels out of ColorDialog1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
        End Sub
    
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim ColorDialog1 As New ColorDialog
            ColorDialog1.FullOpen = True
            If ColorDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
                NewColor = ColorDialog1.Color
            End If
            Label1.Text = "Colors A value = " & NewColor.A.ToString & " and R value = " & NewColor.R.ToString & " and G value = " & NewColor.G.ToString & " and B value = " & NewColor.B.ToString
            Me.BackColor = Color.FromArgb(NewColor.A, NewColor.R, NewColor.G, NewColor.B)
        End Sub
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Monday, November 18, 2013 8:51 PM

All replies

  • You have to create a lookup table.  You can use a dictionary to for the values.  The Color.Red is an enumeration which can be converted to an integer but is not the color value.

    jdweng

    Monday, November 18, 2013 5:47 PM
  • 
    How to convert the str "Color [Red] (saved as object and recovered as string) into System.Drawing.Color = Color.Red

    Well you can use Color.FromName where you use the name of the color and not Color.Red.

    Also color names are case specific so red would not work. If the recovered string is "Color.Red" then split the string at the decimal or period so the array contains Color and Red in index 0 and 1 consecutively.

    Then Color.FromName(SplitArray(1)) should work. In your instance you will need to get Red from between the brackets in the string if the string is "Color [Red]" which you can do with a variety of methods including Regex. If you find that too difficult to do then I will provide a couple of solutions that can do that if you need.

    Option Strict On
    
    Public Class Form1
    
        Dim MyColor As Color
        Dim Test As String = "Color.Red"
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            Dim SplitTest() As String
            SplitTest = Test.Split("."c)
            MyColor = Color.FromName(SplitTest(1))
            Me.BackColor = MyColor
            Me.Text = SplitTest(1)
        End Sub
    
    End Class



    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.



    Monday, November 18, 2013 6:57 PM
  • Option Strict On
    
    Imports System.Text.RegularExpressions
    
    Public Class Form1
    
        Dim Test As String = "Color [Red]"
        Dim FixTest As String = ""
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            FixTest = Test.Replace("Color ", "")
            FixTest = FixTest.Replace("[", "")
            FixTest = FixTest.Replace("]", "")
            Label1.Text = FixTest
    
            FixTest = Test
            Dim Temp = Regex.Match(FixTest, "\[(.*?)\]", RegexOptions.None)
            FixTest = Temp.ToString.Replace("[", "")
            FixTest = FixTest.Replace("]", "")
            Label2.Text = FixTest
    
        End Sub
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Monday, November 18, 2013 7:29 PM
  • Option Strict On
    
    Public Class Form1
    
        Dim Test As String = "Color [Red]"
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
            Label1.Text = GetColor(Test)
        End Sub
    
        Private Function GetColor(ByRef FixIt As String) As String
            Dim Find As Integer = 0
            Find = FixIt.IndexOf("["c)
            FixIt = FixIt.Substring(Find + 1, FixIt.Count - 1 - (Find + 1))
            Return FixIt
        End Function
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.


    Monday, November 18, 2013 8:06 PM
  • Here is the primary question:  will your program only be using known colors, or is it possible for a user to select any color?

    If you are only going to work with named colors from the KnownColor enumeration then you should use color.ToKnownColor.ToString to save the color as a string and Color.FromName (as shown by others) to recreate the color from the string.

    However, if it could be any color that you are saving and loading then none of the suggestions in this thread will work.  Only colors which exactly match a KnownColor will have a name when ToString executes; all others will have RGB values ("Color [A=255, R=237, G=24, B=125]").  So a parsing routine is needed and it must check for one of two different formats, then parse accordingly and use the appropriate FromName or FromArgb methods to create the color.

    -Edit-

    Scratch that - only colors which are created from a known color will result in ToString writing a name.

    If the color is created another way, ToString will print the RBG values; so Color.Red and Color.FromArgb(255,0,0) have different ToString results (even though they are both "Red").


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"


    Monday, November 18, 2013 8:16 PM
    Moderator
  • Yes Reed is absolutely correct. It does depend on what information is in your string since it could be a name if the color is a named color or it could be a hexadecimal value for a color or an ARGB value for a color or possibly something else that I am unfamiliar with.

    Note that in the color dialog in the image I placed the cursor in the blue area of the custom colors window as shown by the object that has two vertical and horizontal lines with the center of where they "meet" as the color of choice and then moved the left facing arrow on the right of the window up to the color I wanted which is displayed in the Color|Solid window before I pressed O.K.

    Option Strict On
    
    Public Class Form1
    
        Dim NewColor As Color = Color.Black ' Default color if user cancels out of ColorDialog1
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.CenterToScreen()
        End Sub
    
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Dim ColorDialog1 As New ColorDialog
            ColorDialog1.FullOpen = True
            If ColorDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
                NewColor = ColorDialog1.Color
            End If
            Label1.Text = "Colors A value = " & NewColor.A.ToString & " and R value = " & NewColor.R.ToString & " and G value = " & NewColor.G.ToString & " and B value = " & NewColor.B.ToString
            Me.BackColor = Color.FromArgb(NewColor.A, NewColor.R, NewColor.G, NewColor.B)
        End Sub
    
    End Class


    Please BEWARE that I have NO EXPERIENCE and NO EXPERTISE and probably onset of DEMENTIA which may affect my answers! Also, I've been told by an expert, that when you post an image it clutters up the thread and mysteriously, over time, the link to the image will somehow become "unstable" or something to that effect. :) I can only surmise that is due to Global Warming of the threads.

    Monday, November 18, 2013 8:51 PM
  • Further to Reed's spanner in the works :P about unknown colours being written in an ARGB format, I put a panel on an empty form as something to change the colour of and used this code:

    Option Infer On Imports System.Text.RegularExpressions Public Class Form1 ''' <summary> ''' Convert a string of the format "color [nameOfColor]" or ''' "color [A=a, R=r, G=g, B=b]" to a System.Drawing.Color. ''' </summary> ''' <param name="s">The </param> ''' <returns>A a System.Drawing.Color.</returns> ''' <remarks>Falls back to fallbackColour if the colour could not be parsed.</remarks> Public Shared Function ColourFromData(s As String) As Color Dim fallbackColour = Color.Black If Not s.StartsWith("color", StringComparison.OrdinalIgnoreCase) Then Return fallbackColour End If ' Extract whatever is between the brackets. Dim re = New Regex("\[(.+?)]") Dim colorNameMatch = re.Match(s) If Not colorNameMatch.Success Then Return fallbackColour End If Dim colourName = colorNameMatch.Groups(1).Value ' Get the names of the known colours. 'TODO: If this function is called frequently, consider creating allColours as a variable with a larger scope. Dim allColours = [Enum].GetNames(GetType(System.Drawing.KnownColor)) ' Attempt a case-insensitive match to the known colours. Dim nameOfColour = allColours.FirstOrDefault(Function(c) String.Compare(c, colourName, StringComparison.OrdinalIgnoreCase) = 0) If Not String.IsNullOrEmpty(nameOfColour) Then Return Color.FromName(nameOfColour) End If ' Was not a named colour. Parse for ARGB values. re = New Regex("A=(\d+).*?R=(\d+).*?G=(\d+).*?B=(\d+)", RegexOptions.IgnoreCase) Dim componentMatches = re.Match(colourName) If componentMatches.Success Then Dim a = Integer.Parse(componentMatches.Groups(1).Value) Dim r = Integer.Parse(componentMatches.Groups(2).Value) Dim g = Integer.Parse(componentMatches.Groups(3).Value) Dim b = Integer.Parse(componentMatches.Groups(4).Value) Return System.Drawing.Color.FromArgb(a, r, g, b) End If Return fallbackColour End Function Private Sub SetBackgroundColour(c As Control, s As String) c.BackColor = ColourFromData(s) End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim testData = "color [A=99, R=99, G=19, B=255]" SetBackgroundColour(Panel1, testData) End Sub End Class


    HTH,

    Andrew

    Monday, November 18, 2013 9:06 PM
  • That looks like a pretty solid parser, Andrew.  :)

    The thing is though, if the OP says that any color is an issue, then I have to wonder why they wouldn't just use To/From ARGB and save/load the resulting integer as a string.  Granted, its not readable as a color to a human, but its a lot less code for sure.  Maybe there is a reason for a person to read the string... though I'm not sure how helpful that will be when the string contains RGB values instead of a color name.


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Monday, November 18, 2013 9:58 PM
    Moderator
  • That looks like a pretty solid parser, Andrew.  :)

    Thanks :) I didn't feel it was worth the effort to make it parse the ARGB format if the components were in a different order, but otherwise I think I've got all possibilities covered for the output of Color.ToString(), even if the case is "incorrect". I was tempted to use Byte.Parse instead of Integer.Parse, but Color.FromArgb() takes integers. And maybe raise a FormatException if the input was not parseable. At least it exposes enough bits to be convertible to parsing floating-point colours or more than 8 bits-per-component.

    --
    Andrew

    Monday, November 18, 2013 10:18 PM
  • I thank you. I am going to try every suggestion.

    Fabio Giannoni

    Brazil

    Tuesday, November 19, 2013 1:05 PM