介绍 考虑到大多数W
inForms控件的灵活性,你可能会认为CheckedListBox会提供一些基本特性,比如项目背景颜色。但不管出于什么原因,它过去是,现在仍然是一种简单而有限的控制。在互联网上搜索一下,你会发现很多关于设置颜色的讨论,建议从重写OnDrawItem到放弃控件,使用列表框。这些充其量只是部分解决方案。 背景 我需要一个定制的CheckedListBox在接口为集成电路晶圆加工机。25个IC晶片被放置在一个塑料盒式磁带中,最多4个盒式磁带可以装入机器。界面显示每个晶圆片的状态(未加工、已加工等),以及某些病理状态,如交叉槽或双槽晶圆片。盒式磁带的插槽也可能是空的。背景色的使用,使整体状态容易确定一目了然。 下面显示的图像取自实际的接口,尽管CheckedListBox的内容是随机生成的测试数据,仅用于验证接口的正确操作。 的愿望清单 一个漂亮的CheckedListBox控件将允许你: 动态设置项目背景颜色动态设置项目前景色动态设置项目字体动态设置项目高度为非标准值控制焦点/选择可视化属性集成visual Studio 意想不到的问题 重写OnDrawItem来处理前景色、背景色和字体的变化应该不是那么困难,或者我是这么认为的。DrawItemEventArgs对象具有前景色、背景色和字体属性。只需实现您想要在一个新的DrawItemEventArgs e2中设置这三个属性的任何逻辑,然后调用base.OnDrawItem(e2)。CheckedListBox有一个ItemHeight属性,所以如果你想让高度独立于字体,它也应该很容易管理。什么也没有做。只是没成功。颜色正确地改变了,但是我所做的任何事情都不能使控件使用我指定的字体,并且项的高度有自己的想法。 卢克,利用线人 那真烦人。是时候再深入挖掘一下了。CheckedListBox的源代码可以从dotnetframework.org在线获得。OnDrawItem(DrawItemEventArgs e)证实了我的怀疑:物品是用e绘制的。字体颜色和e。背景色,但是它完全忽略了e。字体,而不是使用控件的字体。物品的高度是一些神秘计算的焦点。 在这一点上,我只想说,试图将此控件的源代码复制到您自己的项目中,然后修改它来做您想做的事情,这是注定要失败的。但不用担心,因为所有这些问题都有可行的解决方案,尽管并不完美。 它不完美,但它是进步 本文描述了一个名为CustomCheckedListBox的c#类,它是CheckedListBox的子类,提供了希望列表中的所有特性。这个类和VS2015解决方案中的测试驱动程序可以通过这个页面顶部的链接下载。让我们从委托和属性开始: 隐藏,复制Code
public class CustomCheckedListBox : CheckedListBox { public delegate Color GetColorDelegate(CustomCheckedListBox listbox, DrawItemEventArgs e); public delegate Font GetFontDelegate(CustomCheckedListBox listbox, DrawItemEventArgs e); [Description("Supply a foreground color for each item")] public event GetColorDelegate GetForeColor = null; [Description("Supply a background color for each item")] public event GetColorDelegate GetBackColor = null; [Description("Supply a font for each item")] public event GetFontDelegate GetFont = null; [Description("Set this if you don't like the standard selection appearance")] public bool DrawFocusedIndicator { get; set; } public override int ItemHeight { get; set; }
与各种在线解决方案相比,代表是CustomCheckedListBox的第一个大区别。简单地在控件中设置颜色将使所有项目看起来都一样,可能会根据状态进行区分。咩。通过为这些委托提供方法,每个项都可以根据您选择的任何标准着色,并且颜色可以动态更改。同样的机制也可以用于提供每项的字体。对于我的晶圆分拣机,当分拣过程开始时,项目列表是固定的。改变背景颜色以指示晶圆片的当前状态。 这里必须重写ItemHeight属性,因为基类属性实际上是只读的。DrawFocusedIndicator将在下面解释。接下来让我们看一下构造函数。 隐藏,复制Code
public CustomCheckedListBox(GetColorDelegate back = null, GetColorDelegate fore = null, GetFontDelegate font = null) { GetForeColor = fore; GetBackColor = back; GetFont = font; //****************************************************************** // If you want to set the item height to a specific value that can // be independent of the font size, this is the place to do it. //****************************************************************** ItemHeight = 14; }
因为委托都是空的,所以整个类实际上是惰性的,因此在您为这些委托提供方法之前,它的行为就像一个普通的CheckedListBox。还有ItemHeight,我们将在下一节中讨论。它必须在这里初始化,以防止Visual Studio设计器崩溃。默认情况下,ItemHeight设置为14,这似乎与CheckedListBox使用的值相匹配。让我们来看看OnDrawItem方法: 隐藏,收缩,复制Code
protected override void OnDrawItem(DrawItemEventArgs e) { Color foreColor = (GetForeColor != null) ? GetForeColor(this, e) : e.ForeColor; Color backColor = (GetBackColor != null) ? GetBackColor(this, e) : e.BackColor; // // The CheckListBox is going to ignore the font in the event // args and use its own. So, make its own the one we want it // to be. For this to always work right, we will have to shut // down the OnFontChanged method below. // if (GetFont != null) this.Font = GetFont(this, e); // // If desired, draw an item focused, but not selected. // DrawItemState state = (DrawFocusedIndicator) ? ((e.State & DrawItemState.Focus) == DrawItemState.Focus ) ? DrawItemState.Focus : DrawItemState.None : e.State; // // e.Font is going to be ignored. // DrawItemEventArgs e2 = new DrawItemEventArgs(e.Graphics, e.Font, e.Bounds, e.Index, state, foreColor, backColor); base.OnDrawItem(e2); } protected override void OnFontChanged(EventArgs e) { if (GetFont == null) base.OnFontChanged(e); }
基本上,这个方法只是改变DrawItemEventArgs,以反映代表从应用程序获得的每个项目的颜色。if (GetFont != null)行修改基CheckedListBox的字体。在某些情况下,base.OnFontChanged()会导致问题,所以如果我们提供每个项目的字体,就禁用它。 DrawFocusedIndicator抑制正常的视觉选择指示器(基本上,白色项目文本在蓝色背景上)。相反,选中的项将显示wi这是一个聚焦的指标,它只是一个虚线边界。你可以随意打开或关闭这个。 一些警告 首先,您可以为每个项目提供不同的字体,但它们都需要是相同的大小。CheckedListBox不容易处理多个项目的高度。其次,必须在构造函数中设置固定的高度,而且不能更改。 Visual Studio集成 如果将CustomCheckedListBox添加到项目中,并使用Qodex添加到窗体中,Visual Studio将将该控件添加到工具箱中。现在可以将控件拖到窗体上,并像其他控件一样访问其所有属性和事件。这与定制控件不同(这超出了本文的范围),但您可能会发现它完全满足您的需要。 在该表扬的地方表扬 这种控制的灵感来自于这篇StackOverflow文章。虽然它仅限于静态颜色控制,但它为我指明了正确的方向。 轮到你了 就是这样。我希望您觉得这篇文章有趣,甚至可能有用。您可能对CustomCheckedListBox的现状感到满意,或者您可能已经在考虑一些您希望看到的增强功能。也许您希望复选框与项目的背景颜色匹配。让我知道你做了什么聪明的修改。 历史 2015年12月06日:初始版本 本文转载于:http://www.diyabc.com/frontweb/news167.html