Reputation: 711
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
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
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
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
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
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
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)
Upvotes: 6
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
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