65.9K
CodeProject 正在变化。 阅读更多。
Home

禁用时看起来不错的组合框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.24/5 (16投票s)

2006年8月6日

2分钟阅读

viewsIcon

145479

downloadIcon

1438

本文描述了一种自定义绘制组合框的方法,以便在组合框禁用时文本仍然可读。

引言

我一直不喜欢combobox的一件事是,当它被禁用时几乎无法阅读。我有一个应用程序会执行大量的数据绑定,并根据访问规则在后台启用或禁用控件。combobox显示正确的值,但灰色在米色背景上,很难阅读。我不想将它们变成textbox,因为这会使我的代码变得复杂得多(GUI 在运行时生成)。

我在网上做了很多研究,没有找到太多专门处理编辑框外观更改的文章。有很多文章展示了ownerdrawn列表,但只有在listbox启用时才有用。

它看起来是什么样的

如第一个条目所示,禁用的组合框非常难看。第二个条目显示了我的控件的禁用状态 - 更加易读!第三个条目显示控件在启用时正常工作。

我将代码实现为一个简单的combobox子类,因此它可以作为任何使用combobox的地方的替代品。

代码的关键部分

首先,要允许你的组合框被自定义绘制,你必须添加一个DrawItemEventHandler,并将DrawMode设置为OwnerDrawFixed。如果你想更改列表的大小,可以使用OwnerDrawVariable,但这里我没有这样做。我还添加了一个EnabledChanged事件的处理程序。

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

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

接下来,在EnabledChanged事件中,我根据控件是否启用更改了DropDownStyle。只有DropDownDropDownStyle将允许控制输入文本,而DropDownList将只允许使用鼠标。关键是,只有将DropDownStyle设置为DropDownList,才能控制EditBox的外观。对于禁用的控件,这无关紧要,因为无论如何你都无法选择它。

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

最后,这是ownerdraw例程。基本上,你只需根据需要绘制的项目状态,并以你想要的方式绘制它。

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

请注意,如果你使用databinding,你需要在分配标签的行中使用更复杂的代码。也许像这样

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

我希望这对某人有用。这个解决方案非常简单,但花了我很长时间才从各种来源整理出来。欢迎提出任何意见或建议。

许可证

本文没有附加明确的许可,但可能包含文章文本或下载文件本身中的使用条款。如有疑问,请通过下面的讨论区联系作者。作者可能使用的许可列表可以在此处找到。

© . All rights reserved.