Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WinForms

Ownerdrawn ComboBox Example

5.00/5 (10 votes)
5 Jul 2013CPOL2 min read 60.3K  
A sample owner-drawn ComboBox
This tip shows how to change the look of the combobox dropdown list using ownerdrawn ComboBoxes.

Background

So there I was, rummaging around Q&A when I encountered OliveiraGui who had a question about how to change the look of the combobox dropdown list (more specifically, the border color).

He had discovered that there were no properties to change that, and my reply to him was that it could be done, but that he had to ownerdraw the ComboBox to do it, and I gave him a few examples of ownerdrawn comboboxes.

Painting your own ComboBox is not really that hard, nor is it that complicated or requires a lot of code. The important part is knowing how to do it. It helps if you have meddled around with drawing in GDI+ or if you have done a fair amount of custom control development.

Afterwards, I thought about it, and I found the question interesting enough to do a small sample for him.

The thing is that even with owner-drawing, it's not really that easy to get access to the dropdown window itself. But it's quite easy to change the appearance of the individual items and thus mimic that the entire window has been changed.

So here is a ComboBox where you can change the BorderColor and BackColor of the dropdown list. For demonstration purposes, I've made the default color values red and yellow. If you were to use this code in a real project, it would probably be a good idea to change that to black and white.

If you study the code, you will see that it is also very easy to change the appearance of the individual items in the dropdown list, e.g., the forecolor, font, etc. But I leave that up to you as a follow-up exercise.

The Code

C#
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace OwnerDrawnComboBoxTest
{
    [ToolboxBitmap(typeof(ComboBox))]
    class ComboBoxEx : ComboBox
    {
        public ComboBoxEx()
        {
            this.DrawMode = DrawMode.OwnerDrawFixed;
            this.DrawItem += ComboBoxEx_DrawItem;
            this.DropDownBorderColor = Color.Red;
            this.DropDownBackColor = Color.Yellow;
        }

        [Category("Appearance")]
        [Description("The border color of the drop down list")]
        [DefaultValue(typeof(Color), "Red")]
        public Color DropDownBorderColor { get; set; }

        [Category("Appearance")]
        [Description("The background color of the drop down list")]
        [DefaultValue(typeof(Color), "Yellow")]
        public Color DropDownBackColor { get; set; }

        private void ComboBoxEx_DrawItem(object sender, DrawItemEventArgs e)
        {
            if (e.Index < 0)
                return;

            if ((e.State & DrawItemState.ComboBoxEdit) == DrawItemState.ComboBoxEdit)
                return;

            // Draw the background of the item
            if (
                ((e.State & DrawItemState.Focus) == DrawItemState.Focus) ||
                ((e.State & DrawItemState.Selected) == DrawItemState.Selected) ||
                ((e.State & DrawItemState.HotLight) == DrawItemState.HotLight)
               )
            {
                e.DrawBackground();
            }
            else
            {
                using (Brush backgroundBrush = new SolidBrush(DropDownBackColor))
                {
                    e.Graphics.FillRectangle(backgroundBrush, e.Bounds);
                }
            }

            //Draw item text
            e.Graphics.DrawString(Items[e.Index].ToString(), this.Font, Brushes.Black,
              new RectangleF(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height));

            // Draw the focus rectangle if the mouse hovers over an item
            if ((e.State & DrawItemState.Focus) == DrawItemState.Focus)
                e.DrawFocusRectangle();

            //Draw the border around the whole DropDown area
            using (Pen borderPen = new Pen(DropDownBorderColor, 1))
            {
                Point start;
                Point end;

                if (e.Index == 0)
                {
                    //Draw top border
                    start = new Point(e.Bounds.Left, e.Bounds.Top);
                    end = new Point(e.Bounds.Left + e.Bounds.Width - 1, e.Bounds.Top);
                    e.Graphics.DrawLine(borderPen, start, end);
                }

                //Draw left border
                start = new Point(e.Bounds.Left, e.Bounds.Top);
                end = new Point(e.Bounds.Left, e.Bounds.Top + e.Bounds.Height - 1);
                e.Graphics.DrawLine(borderPen, start, end);

                //Draw Right border
                start = new Point(e.Bounds.Left + e.Bounds.Width - 1, e.Bounds.Top);
                end = new Point(e.Bounds.Left + e.Bounds.Width - 1, 
                                e.Bounds.Top + e.Bounds.Height - 1);
                e.Graphics.DrawLine(borderPen, start, end);

                if (e.Index == Items.Count - 1)
                {
                    //Draw bottom border
                    start = new Point(e.Bounds.Left, e.Bounds.Top + e.Bounds.Height - 1);
                    end = new Point(e.Bounds.Left + e.Bounds.Width - 1, 
                                    e.Bounds.Top + e.Bounds.Height - 1);
                    e.Graphics.DrawLine(borderPen, start, end);
                }
            }
        }
    }
}

History

  • Version 1.03 - Added Using
  • Version 1.02 - Added check for Index=-1 and State=ComboBoxEdit - That is necessary if the ComboBox style is DropDownList
  • Version 1.01 - Changed the testing of the e.State flag
  • Version 1.00 - Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)