XTab's Blog

Ged Mead's Blog at vbCity

This blog hosted by:
http://blogs.vbcity.com      
  Home :: Syndication  :: Login

AprMay 2008Jun
SMTWTFS
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

Archives

Topics

Ramblings

VB.NET

  I saw a couple of unrelated questions on vbCity recently - one was about PropertyInfo  and  the other was in regard to Colors - and seeing them reminded me about how easy it is to use PropertyInfo to get access to and list all the 141 named Colors.  There are of course other ways of doing this, but I just thought it would be a fun approach to use.

  The following example is based on a Windows Form that contains a Button and a ListBox for demo purposes.

   First create an array to hold the Colors once we've dug them out of the Colors structure:

Code Copy
Dim Colorprops() As Reflection.PropertyInfo
 

  Next, in the button click event:

Code Copy
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        '  To get hold of the  Members of the Color Structure
        '  the GetProperties method returns an array of properties in the Color structure
        '  and we store them in the ColorProps array
        ColorProps = GetType(System.Drawing.Color).GetProperties

        '  For demo purposes, display the contents of the array in a listbox
        '  We use the Name property to return the string assigned to each property in turn
        For x As Integer = 0 To ColorProps.Length - 1
            ListBox1.Items.Add((ColorProps(x).Name))
        Next

    End Sub

   As you can see from the code comments, thanks to the magic of Reflection it's very easy to get an array that contains all the Colors, which are stored as properties in the Color structure.  This is achieved in the first code line.     Then just for demo purposes I've displayed all the names of the Colors in a listbox.

   Of course, if you've gone to the trouble of creating this list you have probably done so because you actually want to do something with the colors.  For example, you might want to let the user change the BackColor of the current form.

   The potential problem here is that the listbox now contains a list of strings.  I know we tend to look at a list like that and can visualise them as colors, but the compiler isn't quite that clever and needs a little human help.   So what we can do is to instruct it to take the selected string from the listbox (which represents the desired color) and turn that back into an actual Color object - and this can then be assigned as the Form's BackColor. 

   You might consider using this code to do the job :

Code Copy
    Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
            BackColor = Color.FromName(ListBox1.SelectedItem.ToString)
    End Sub

  and it will work .....  up to a point.   However, the first item in the list is the Transparent property, which is a valid Color in many situations but sadly not one that a Windows Form will accept as its BackColor.

   At the other end of the list you will see other Color properties, such as R, G, B, A, IsKnownColor and so on.   Again these more obviously are not going to be valid BackColor properties for the Form.

  As always, alternative solutions are available.   Perhaps the easiest one would simply be to wrap the code in an Exception Handler which will then gracefully and silently ignore any non-valid choice:

Code Copy
    Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged

        Try
            BackColor = Color.FromName(ListBox1.SelectedItem.ToString)
        Catch ex As Exception

        End Try

    End Sub

    Is this a good fix?   Probably depends on the scenario you're using it in.  If you're planning on exposing this Form to a non-tech savvy user then I'd say it's a pretty poor workaround.  They might not understand or be happy that the choice they're making is unacceptable and nothing is happening.  Of course you could slip a message box into the Catch block, but personally I think it would be better not to show them unusable choices at all in the first place and so avoid the problem.

   So let's look at how we might do that.

   I suppose you could exclude the first Color (Transparent) and the final nine ("R" to "Name" inclusive) simply by changing the first line of the loop to:

              For x As Integer = 1 To 140

 but I'm not crazy about that approach, even though it would work just fine. 

  My preference would be to try and filter in only those Colors that are system defined Public Shared Colors - that is, the named Colors themselves and effectively excluding the final nine entries in the list which are instance members.  Once again Reflection makes this a very easy task.

  The GetProperties method takes BindingFlags as parameters and you can use these to filter the search.  In our case we will use the Public and Static BindingFlags.  (You don't have to remember all the available Flags as the full enumeration of them will be displayed as soon as you type an opening bracket after "GetProperties"): -

Code Copy
  ColorProps = GetType(System.Drawing.Color).GetProperties(BindingFlags.Public Or BindingFlags.Static)

   If you run the code again you will now only offer the 141 Colors to the user via the ListBox.   "Transparent" is of course a valid Color so it's right that it appears in the list of Colors.  But because we have refined the task to assign the Colors to the Form's BackColor, we still have to resolve this.

  Again, a quick and acceptable fix would be to use a Try Catch Exception Handler.

   But what if our scenario really was one where we want to allow the user to change the Form's BackColor to Transparent?  Well we quite easily do this by intercepting the user's choice and if it turns out to be a choice of "Transparent" then we can manually make the whole form transparent by changing its Opacity property.

  Now, I know this isn't a 100% fix for making the BackColor transparent because the transparency effect is applied to the whole form, not just the client area.  Unfortunately the ClientRectangle doesn't have its own Opacity property, so I think that this code will be the nearest we can get:

 

Code Copy
Dim col As New Color
        col = Color.FromName(ListBox1.SelectedItem.ToString)
        If col.Name = "Transparent" Then
            Me.Opacity = 0.15
        Else
            BackColor = col
        End If

 

      The allowed values for Opacity range from 0 (invisible) to 1 (fully visible).  I purposely didn't set the value to 0, because of course this would mean that the user would lose the total form from view and wouldn't even be able to access the title bar to, for example, close the form.

   In fact, I'd be inclined to make the whole deal a bit more user friendly by showing the user a one-time message about how to remove the Transparent setting.  So the ListBox selection code would now be:

 

Code Copy
  Dim msgshown As Boolean

    Private Sub ListBox1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged

        Dim col As New Color
        col = Color.FromName(ListBox1.SelectedItem.ToString)
        If col.Name = "Transparent" Then
            Me.Opacity = 0.15
            If Me.msgshown = False Then
                MessageBox.Show("Double Click the form to undo the Transparent setting", "Info", MessageBoxButtons.OK)
                msgshown = True
            End If
        Else
            BackColor = col
        End If

    End Sub

   and in order to implement that reinstatement of full Opacity, you would just need :-

Code Copy
    Private Sub Form1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.DoubleClick
        Me.Opacity = 1
    End Sub

   So that's it.   Dealing with colors (as color objects and not as names that we visualise in our heads as actual colors) can be a bit tricky until you get used to how it works.  I hope that this relatively simple walkthrough has helped clarify things for you.

  

posted on Friday, November 09, 2007 5:04 PM

Feedback

No comments posted yet.

Post Feedback

Title:
Name:
Url:
Comments: 
Protected by Clearscreen.SharpHIPEnter the code you see: