Elhendriks
Elhendriks

Reputation: 119

Display Colors in ComboBox from aRGB Value item

My problem is the following:

I have a Combobox filled with aRGB codes (extracted from an excel file), like this:

255, 149, 55, 39
255, 0, 176, 80
255, 0, 112, 192
...

My goal is to display a list of colors instead of their rgb code. So, I tried to do this, unsuccessfully:

 Private Sub CB_Color_DrawItem(ByVal sender As System.Object, ByVal e As DrawItemEventArgs) Handles CB_Color.DrawItem

    If e.Index = -1 Then
        Exit Sub
    End If

    Dim colBrush As Brush = New SolidBrush(Color.FromArgb(CB_Color.Items(e.Index)))
    'Drawing rectangles for the color values
    e.Graphics.DrawRectangle(New Pen(Brushes.Black), e.Bounds.Left + 2, 
                       e.Bounds.Top + 2, 30, e.Bounds.Height - 5)
    e.Graphics.FillRectangle(colBrush, e.Bounds.Left + 3, e.Bounds.Top + 3, 
                       29, e.Bounds.Height - 6)

End Sub

This code doesn't change anything. I still have rbg codes in my combobox's list. Can anyone please tell me what's wrong whith this code?

Upvotes: 1

Views: 1254

Answers (2)

You have several problems. As noted, if the Text is being drawn and your DrawItem code isnt drawing it, then DrawMode is probably not set to OwnderDrawFixed.

Then, once you say you will handle drawing the items, you have to handle all the drawing. That includes the Selected item highlighting, the background and the focus rectangle. The little color boxes you draw leave room to also display the text, so this will show how to do both.

Private Sub cbox1_DrawItem(sender As Object, e As DrawItemEventArgs) Handles cbox1.DrawItem
    If e.Index = -1 Then Return

    Dim thisText As String = cbox1.Items(e.Index).ToString()
    Dim thisColor As Color = CType(TypeDescriptor.GetConverter(GetType(Color)).
                                            ConvertFromInvariantString(thisText), 
                                            Color)
    ' use HeighLight when needed
    Dim foreclr As Color = If(e.State.HasFlag(DrawItemState.Selected),
                              SystemColors.HighlightText,
                              cbox1.ForeColor)

    e.DrawBackground()
    Using br As New SolidBrush(thisColor)
        e.Graphics.DrawRectangle(New Pen(Brushes.Black),
                                 e.Bounds.Left + 2, e.Bounds.Top + 2, 30,
                                 e.Bounds.Height - 5)
        e.Graphics.FillRectangle(br, e.Bounds.Left + 3, e.Bounds.Top + 3,
                     29, e.Bounds.Height - 6)

        Dim tRect = New Rectangle(e.Bounds.Left + 32, e.Bounds.Top + 2,
                                  e.Bounds.Width - 32, e.Bounds.Height - 4)
        TextRenderer.DrawText(e.Graphics, String.Format("255, {0:000}, {1:000}, {2:000}",
                                              thisColor.R, thisColor.G, thisColor.B),
                                              cbox1.Font, tRect, foreclr)
    End Using

    e.DrawFocusRectangle()

End Sub

The format of the ARGB string appears to be the InvariantString format which is used in all sorts of export and serialization. The code shows how to convert using it, but String.Split will work too. You will have to do the same when they make a selection to actually create a color from the text (or do all that up front and run off a List(Of Color))

The important thing is to check to see if the item is the Selected item and use the correct forecolor for any text you do draw. TheFocusRectangle is also shown.

There is plenty of room for both the text and a color swatch, but if you really do not want the ARGB text, just skip the DrawText code, and consider filling the entire rectangle with color rather than drawing a swatch:

enter image description here

Upvotes: 4

Megan
Megan

Reputation: 44

Firstly in the combobox properties find the property called "DrawMode". Change this value to 'OwnerDrawFixed'. This is the value that indicates if the code or the operating system will handle the drawing.

Then you will need to add and change the following code:

Dim colorArray() As String = ComboBox1.Items(e.Index).ToString.Split(",")

Dim colBrush As Brush = New SolidBrush(Color.FromArgb(CInt(colorArray(0)), CInt(colorArray(1)), CInt(colorArray(2)), CInt(colorArray(3))))

We do this because the FromARGB only accepts integer values.

Upvotes: 2

Related Questions