JBB
JBB

Reputation: 711

How to change combobox background color (not just the drop down list part)

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

Upvotes: 31

Views: 74260

Answers (8)

Edgar5
Edgar5

Reputation: 51

Here is a more generic handler procedure which shows how to control the text and the background colors. It also extracts the ComboBox from “sender”:

private void ComboBox_DrawItem(object sender, DrawItemEventArgs e) {
   if (e.Index < 0)
      return;
   ComboBox comboBox = sender as ComboBox;
   int index = e.Index;
   Brush textBrush, backgroundBrush;

   if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) {
      textBrush = new SolidBrush(Color.Yellow);
      backgroundBrush = new SolidBrush(Color.Blue);
   }
   else {
      textBrush = new SolidBrush(Color.Red);
      backgroundBrush = new SolidBrush(Color.YellowGreen);
   }
   e.DrawBackground();

   if (index != -1) {
      Rectangle rectangle = new Rectangle(2, e.Bounds.Top + 2, e.Bounds.Width - 4, e.Bounds.Height - 4);
      e.Graphics.FillRectangle(backgroundBrush, rectangle);
      e.Graphics.DrawString(comboBox.Items[index].ToString(), e.Font, textBrush, e.Bounds, StringFormat.GenericDefault);
   }
   e.DrawFocusRectangle();
}

Upvotes: 0

ourmandave
ourmandave

Reputation: 1585

Stole @TheJonz idea and made a subroutine that autogens the background labels for every flat combobox on a parent control.

(I only had one parent but if you had many you could mod it to pass in a parent or do the recursive controls loop thing from the base form.)

  Private Sub ComboBoxBorders()

    Dim cX As ComboBox    
    Dim i As Integer = 0

    For Each c As Control In pnlMain.Controls

      If TypeOf c Is ComboBox Then

        cX = c

        If cX.FlatStyle <> FlatStyle.Flat Then
          Continue For
        End If

        Dim l As New Label

        l.Name = $"LX{i}"
        l.AutoSize = False
        l.BorderStyle = BorderStyle.FixedSingle
        l.Size = New Size(c.Width + 4, c.Height + 4)
        l.Location = New Point(c.Left - 1, c.Top - 1)
        l.BackColor = pnlMain.BackColor

        i += 1

        pnlMain.Controls.Add(l)
        l.SendToBack()
    
      End If

    Next

  End Sub

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

Upvotes: 0

Eduardo Flores
Eduardo Flores

Reputation: 81

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

Upvotes: 1

bob number 2
bob number 2

Reputation: 55

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 ();
}

Upvotes: 3

Sasha Bond
Sasha Bond

Reputation: 1176

    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();
        }
    }

Upvotes: 0

blind Skwirl
blind Skwirl

Reputation: 341

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

Upvotes: 6

bambams
bambams

Reputation: 765

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...

Upvotes: 13

Igby Largeman
Igby Largeman

Reputation: 16747

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.

Upvotes: 26

Related Questions