29

In a winform application running on windows 7 I want the change the background color of a combobox to highlight it. The comboxbox has a DropDownStyle of DropDownList.

When I programmatically change the BackColor property to Red, only the background of the actual drop down list is changed to Red. When the drop down list is not opened, the combobox background displaying the selected value remains grey. What can I do so it becomes red too?

Setting the BackColor property works fine when app is run on Windows XP

Cœur
  • 37,241
  • 25
  • 195
  • 267
JBB
  • 691
  • 2
  • 8
  • 13

6 Answers6

26

This should get you started.

Change the combobox DrawMode property to OwnerDrawFixed, and handle the DrawItem event:

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    int index = e.Index >= 0 ? e.Index : 0;
    var brush = Brushes.Black;
    e.DrawBackground();
    e.Graphics.DrawString(comboBox1.Items[index].ToString(), e.Font, brush, e.Bounds, StringFormat.GenericDefault);
    e.DrawFocusRectangle();
}

The background color will be right but the style of the box will be flat, not the usual 3D style.

Igby Largeman
  • 16,495
  • 3
  • 60
  • 86
  • 8
    Thanks that's a good start. Does anyone know how to change the background color and preserve the 3D style? – JBB Jun 25 '11 at 10:14
  • Very helpful! Thank you. I had to add... if (e.Index == -1) return; --- as I got a 'System.ArgumentOutOfRangeException' when loading. Also, would be nice to change the background color when focused. – Leo Gurdian Dec 29 '16 at 18:30
11

Since you lose the 3D effects anyway with Igby Largeman's solution you're better off changing the FlatStyle property to Flat. The background color seems to be obeyed even in Windows 7 that way, and without re-implementing any low-level events.

I would consider this a bug on Microsoft's part...

bambams
  • 745
  • 1
  • 8
  • 18
  • This results in a very different appearance and also results in some rather annoying flickering artifacts. – James Johnston Oct 20 '15 at 17:57
  • 1
    It was giving me issue on Windows Server 2012 R2. Same was working fine on Windows Server 2008. Changing the `FlatStyle` to `Flat` works. You saved my day at a very crucial juncture. – RBT Aug 03 '16 at 12:55
  • This is close, annoyingly the border is whit instead of black like the Textbox – pauloya Jul 28 '22 at 22:11
6

I played around with this for a while and didn't want to do anything too involved. Those ideas above probably work but all I did was change the flatStyle property from "standard" to "flat".

Although not perfect, it at least changes the background that grey/disabled look to white.

You can see the comparison here:

Heating Source #1 > DropdownList > flat (the final decision since dropdown was allowing users to enter bad data)

Heater Source #2 > Dropdown > Standard (the default which looks nice)

Housing Type > Dropdown > Flat

Heating Source #1 Vendor > DropdownList > Standard (the default which looks disabled grey)

enter image description here

blind Skwirl
  • 321
  • 3
  • 6
  • 2
    My form background color is white and I really didn't like how the Combobox just blended into the background when I set the FlatStyle to Flat so this is what I did to make it look better... I added a Label to the form, set BorderStyle of the Label to FixedSingle, set AutoSize to False and then right mouse clicked on it and selected "Send to Back" then I resized the Label to be slightly larger than the Combobox and put the Label right behind the Combobox and now it looks good. – TheJonz Aug 22 '18 at 00:52
2

Igby Largeman's answer got me 95% of the way there. And credit to Sasha Bond for the Brush colouring for setting the HighlightText colour when selected.

Some improvements I made to get me to 100% are adding brush colour from the ComboBox's ForeColor and handling when the index is -1 (and setting it to -1 to start with so it behaves exactly like a normal dropdownstyle ComboBox).

Best of all, when setting this back to a standard dropdown style, it still behaves normally.

private void comboBox1_DrawItem ( object sender, DrawItemEventArgs e )
{
  int index = e.Index >= 0 ? e.Index : -1;
  Brush brush = ( ( e.State & DrawItemState.Selected ) > 0 ) ? SystemBrushes.HighlightText : new SolidBrush ( comboBox1.ForeColor );
  e.DrawBackground ();
  if ( index != -1 )
  {
    e.Graphics.DrawString ( comboBox1.Items[index].ToString (), e.Font, brush, e.Bounds, StringFormat.GenericDefault );
  }
  e.DrawFocusRectangle ();
}
1

Here is what i used for a vb project for another beginner that might be interested. One can use the sender of the event as the combobox that triggered it. By casting it, you can have access to the elements of the list. I also changed the graphics TextRenderingHint for better font display.

Private Sub PaintComboBoxItem(sender As Object, e As DrawItemEventArgs)
    Dim combobox As ComboBox = sender
    Dim index As Integer = If(e.Index >= 0, e.Index, 0)
    Dim brush As Brush = If(combobox.Enabled,
                                New SolidBrush(m_UITheme.TitleColor),
                                New SolidBrush(m_UITheme.White))
    e.Graphics.SmoothingMode = SmoothingMode.HighQuality
    e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit
    e.DrawBackground()
    e.Graphics.DrawString(combobox.Items(index).ToString(), combobox.Font, brush, e.Bounds, StringFormat.GenericDefault)
    e.DrawFocusRectangle()
End Sub
0
    private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
    {
        var cmb = (ComboBox) sender;
        if (cmb == null) return;

        if (e.Index % 2 == 0)
        {
            e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds);
            e.Graphics.DrawString(cmb.Items[e.Index].ToString(), cmb.Font, SystemBrushes.GrayText, e.Bounds);
        }
        else
        {
            e.DrawBackground();

            // change background color
            e.Graphics.FillRectangle(Brushes.AntiqueWhite, e.Bounds);

            // change foreground color
            Brush brush = ((e.State & DrawItemState.Selected) > 0) ? SystemBrushes.HighlightText : SystemBrushes.ControlText;

            e.Graphics.DrawString(cmb.Items[e.Index].ToString(), cmb.Font, brush, e.Bounds);
            e.DrawFocusRectangle();
        }
    }
Sasha Bond
  • 984
  • 10
  • 13