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






4.24/5 (16投票s)
2006年8月6日
2分钟阅读

145479

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
。只有DropDown
的DropDownStyle
将允许控制输入文本,而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]);
我希望这对某人有用。这个解决方案非常简单,但花了我很长时间才从各种来源整理出来。欢迎提出任何意见或建议。
许可证
本文没有附加明确的许可,但可能包含文章文本或下载文件本身中的使用条款。如有疑问,请通过下面的讨论区联系作者。作者可能使用的许可列表可以在此处找到。