Click here to Skip to main content
15,881,852 members
Articles / Programming Languages / C#

A Combobox that Looks Decent When it is Disabled

Rate me:
Please Sign up or sign in to vote.
4.24/5 (17 votes)
6 Aug 20062 min read 142.6K   1.4K   55   22
This article describes a method to ownerdraw a combo box so that the text is readable when the combobox is disabled.

Introduction

One of the things I have never liked about the combobox is that it is almost unreadable when it is disabled. I have an application that does a lot of databinding and enables or disables controls behind the scenes based upon access rules. The comboboxes show the right values, but it is grey on beige, and very hard to read. I don't want to make them textboxes because it would make my code considerably more complex (the GUI is generated at runtime).

I did a lot of research on the web and didn't find too many articles that dealt specifically with changing the appearance of the edit box. There are lots of articles that show an ownerdrawn list, but that only is helpful when the listbox is enabled.

What It Looks Like

Image 1

As you can see in the first entry, the disabled combo is pretty ugly. The second entry shows my control in a disabled state - much more readable! The third entry shows that the control works normally when enabled.

I implemented the code as a simple subclass from combobox, so it can be dropped in as a replacement anywhere a combobox is used.

Key Parts of the Code

First, to allow your combo to be owner drawn, you have to add a DrawItemEventHandler and also set the DrawMode to OwnerDrawFixed. You can use OwnerDrawVariable if you want to change the size of the list, but I am not doing that here. I also added a handler for EnabledChanged event.

C#
// Required for ownerdraw
this.DrawItem += new DrawItemEventHandler(EnableDisplayCombo_DrawItem);

// Required for ownerdraw
this.DrawMode = DrawMode.OwnerDrawFixed;
this.EnabledChanged += new EventHandler(EnableDisplayCombo_EnabledChanged);

Next, in the EnabledChanged event, I change the DropDownStyle based upon whether the control is enabled or not. A DropDownStyle of just DropDown will allow the control to be typed into, but DropDownList will only allow the use of the mouse. The catch is that you can only control the appearance of the EditBox if you set the DropDownStyle to DropDownList. For a disabled control, it doesn't matter since you can't select it anyway.

C#
void EnableDisplayCombo_EnabledChanged(object sender, EventArgs e)
{
    if (this.Enabled)
        this.DropDownStyle = ComboBoxStyle.DropDown;
    else
        this.DropDownStyle = ComboBoxStyle.DropDownList;
}

Finally, here is the ownerdraw routine. Basically, you just key on the state of the item that needs to be drawn, and draw it however you want.

C#
void EnableDisplayCombo_DrawItem(object sender, DrawItemEventArgs e)
{    
    System.Drawing.Graphics g = e.Graphics;    
    Rectangle r = e.Bounds;    
    if (e.Index >= 0)    
    {        
        string label = this.Items[e.Index].ToString();        
        // This is how we draw a disabled control        
        if (e.State == (DrawItemState.Disabled | DrawItemState.NoAccelerator 
                | DrawItemState.NoFocusRect | DrawItemState.ComboBoxEdit))   
        {            
            e.Graphics.FillRectangle(new SolidBrush(Color.White), r);      
            g.DrawString(label, e.Font, Brushes.Black, r);            
            e.DrawFocusRectangle();        
        }        
        
        // This is how we draw the items in an enabled control that aren't
        // in focus        
        else if (e.State == (DrawItemState.NoAccelerator | 
                             DrawItemState.NoFocusRect))        
        {            
            e.Graphics.FillRectangle(new SolidBrush(Color.White), r); 
            g.DrawString(label, e.Font, Brushes.Black, r);            
            e.DrawFocusRectangle();        
        }        
        
        // This is how we draw the focused items        
        else        
        {            
            e.Graphics.FillRectangle(new SolidBrush(Color.Blue), r); 
            g.DrawString(label, e.Font, Brushes.White, r);            
            e.DrawFocusRectangle();        
        }    
    }    
    g.Dispose();
}

Note that if you use databinding, you will have to use a little more complex code in the line where the label is assigned. Maybe something like this:

C#
string label = Convert.ToString(item[this.DisplayMember]);

I hope this is useful to somebody. The solution is pretty simple, but it took me a long time to piece it together from various sources. Any comments or suggestions are very welcome.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below. A list of licenses authors might use can be found here.


Written By
Web Developer
United States United States
Alex Kilpatrick started writing software in 1981, modifying computer games written in basic. Since then, he has dabbled off and on in about 15 different languages, but currently prefers C#.

Comments and Discussions

 
SuggestionKIS Pin
Jorge_Cruz28-May-16 7:18
Jorge_Cruz28-May-16 7:18 
GeneralUnneeded Dispose Pin
Michael Ehrt24-May-11 0:54
Michael Ehrt24-May-11 0:54 
GeneralUnreleased resources Pin
j4v127-Aug-10 11:40
j4v127-Aug-10 11:40 
GeneralMissing Row Highlight Pin
j4v127-Aug-10 11:26
j4v127-Aug-10 11:26 
GeneralBug Update Pin
Bib3477016-Sep-09 22:10
Bib3477016-Sep-09 22:10 
Questionif comboBox's DropDownStyle = ComboBoxStyle.Simple, It looks as regular comboBox when disabled. Pin
flyrain00022-Jul-09 16:08
flyrain00022-Jul-09 16:08 
GeneralVery good tutorial! Thanks very much! Pin
sti_sti12-Aug-08 23:36
sti_sti12-Aug-08 23:36 
GeneralAwesome Pin
Rakesh B Singh2-Jun-07 0:28
Rakesh B Singh2-Jun-07 0:28 
GeneralDatabinding revisited Pin
Johnny J.26-Apr-07 4:53
professionalJohnny J.26-Apr-07 4:53 
GeneralRe: Databinding revisited Pin
annielhy20-Jun-08 16:49
annielhy20-Jun-08 16:49 
GeneralDropDownList Pin
Johnny J.24-Apr-07 0:16
professionalJohnny J.24-Apr-07 0:16 
GeneralUpdate for WinXP and W2K3 Pin
Rine21-Mar-07 22:44
Rine21-Mar-07 22:44 
QuestionHow to handle databound combobox Pin
sjoske13-Sep-06 3:48
sjoske13-Sep-06 3:48 
GeneralNice, but a few comments though Pin
Henk van der Geld8-Aug-06 6:07
Henk van der Geld8-Aug-06 6:07 
GeneralRe: Nice, but a few comments though Pin
Abhlu10-Oct-06 16:22
Abhlu10-Oct-06 16:22 
GeneralASP.NET Version Pin
rjpaulsen7-Aug-06 4:49
rjpaulsen7-Aug-06 4:49 
GeneralRe: ASP.NET Version Pin
AlexKilpatrick7-Aug-06 5:15
AlexKilpatrick7-Aug-06 5:15 
GeneralExcellent Trick !! Pin
Marcos Meli7-Aug-06 3:45
Marcos Meli7-Aug-06 3:45 
GeneralI'll certainly have to take a look Pin
Ilíon7-Aug-06 3:18
Ilíon7-Aug-06 3:18 
GeneralRe: I'll certainly have to take a look Pin
AlexKilpatrick7-Aug-06 5:17
AlexKilpatrick7-Aug-06 5:17 
Actually, this is not a bad solution at all, if you can use it.

A disabled text box has the same ugliness. In my code, I switch a disabled textbox for a label, because it is much easier to read.

However, to switch a combo box for a textbox would be more complicated because I would have to do the database lookup for the value. With a combobox, that is already handled via databinding.
GeneralRe: I'll certainly have to take a look Pin
Ilíon7-Aug-06 9:10
Ilíon7-Aug-06 9:10 
GeneralRe: I'll certainly have to take a look Pin
Ilíon18-Aug-06 13:42
Ilíon18-Aug-06 13:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.