在一个点对点文件传输的项目中我需要显示文件传输的实时信息传输的文件列表和当前传输的文件当时我想到了用ListBox但是但我用了ListBox后我发现它不能改变控件中文本想的颜色于是我就想扩展一下ListBox控件ListBoxEx
我的目标是给空间加上图标还要能时时改变控件文本颜色于是从ListBox派生类
public class ListBoxEx : ListBox {…}
为了操作方便我为ListBoxEx的每一项设计专门的类ListBoxExItem
public class ListBoxExItem {…}
为了保持我这个控件与WinForm的标准控件的操作借口一致我又重新设计了两个集合类:
public class ListBoxExItemCollection : IList ICollection IEnumerator {}
//这个类相对于标准ListBox中的ObjectCollection这个类作为ListBoxEx中的Items属性的类型
public class SelectedListBoxExItemCollection : : IList ICollection IEnumerator{}
//这个类相对于标准ListBox中的SelectedObjectCollection这个类作为ListBoxEx中的SelectedItems属性的类型
下面看两个集合类的实现
ListBoxExItemCollection的实现为了做到对集合(Items)的操作能够及时反映到ListBoxEx的控件中所以此类只是对ListBox中Items(ObjectCollection类型)作了一层包装就是把ListBox中Items属性的所有方法的只要是object类型的参数都转换成ListBoxExItem比如:
public void Remove(ListBoxExItem item)
{
this_ItemsRemove(item); //_Items为ObjectCollection类型
}
public void Insert(int index ListBoxExItem item)
{
this_ItemsInsert(index item);
}
public int Add(ListBoxExItem item)
{
return this_ItemsAdd(item);
}
由上可知ListBoxExItemCollection中有一个构造函数来传递ListBox中的Items对象
private ObjectCollection _Items;
public ListBoxExItemCollection(ObjectCollection baseItems)
{
this_Items = baseItems;
}
而SelectedListBoxExItemCollection类的实现也用同样的方法只不过是对SelectedObjectCollection包装罢了
集合实现后再来看ListBoxExItem的实现
为了使它支持图标和多种颜色添加如下成员
private int _ImageIndex;
public int ImageIndex
{
get { return this_ImageIndex; }
set { this_ImageIndex = value;}
}
private Color _ForeColor;
public Color ForeColor
{
get{ return this_ForeColor;}
set
{
this_ForeColor = value;
thisParentInvalidate();
}
}
当然还有
private string _Text;
public string Text
{
get { return this_Text; }
set { this_Text = value; }
}
为了控件能正确显示此项的文本还必须重写ToString()方法
public override string ToString()
{
return this_Text;
}
再看ListBoxEx的实现:
为了使控件能够自我绘制所以DrawMode = DrawModeOwnerDrawFixed;
为了覆盖基类的Items等相关属性添加
private ListBoxExItemCollection _Items; //在构造函数中创建
同时还需要重写属性Items
new public ListBoxExItemCollection Items
{
get
{
return this_Items;
}
}
new public ListBoxExItem SelectedItem //强制转换为ListBoxExItem
{
get{ return baseSelectedItem as ListBoxExItem;}
set{ baseSelectedItem = value;}
}
new public SelectedListBoxExItemCollection SelectedItems //重新包装SelectedItems
{
get
{
return new SelectedListBoxExItemCollection(baseSelectedItems);
}
}
为了支持图标添加一个图像列表imagelist
private ImageList imageList;
public ImageList ImageList
{
get { return thisimageList; }
set
{
thisimageList = value;
thisInvalidate();//图像列表改变后马上更新控件
}
}
而此控件的核心却在一个方法OnDrawItem这个方法每当控件的项需要重绘时就被调用
protected override void OnDrawItem(SystemWindowsFormsDrawItemEventArgs pe)
{
peDrawBackground(); //画背景
peDrawFocusRectangle(); //画边框
Rectangle bounds = peBounds;
// Check whether the index is valid
if(peIndex >= && peIndex < baseItemsCount)
{
ListBoxExItem item = thisItems[peIndex]; //取得需要绘制项的引用
int iOffset = ;
// If the image list is present and the image index is set draw the image
if(thisimageList != null)
{
if (itemImageIndex > && itemImageIndex < thisimageListImagesCount)
{
thisimageListDraw(peGraphics boundsLeft boundsTop boundsHeight boundsHeight itemImageIndex); //绘制图标
}
iOffset += boundsHeight;//thisimageListImageSizeWidth;
}
// Draw item text
peGraphicsDrawString(itemText peFont new SolidBrush(itemForeColor)boundsLeft + iOffset boundsTop); //根据项的颜色绘制文本
}
baseOnDrawItem(pe);
}
}
到此为止ListBoxEx以完整的实现并且支持可视化设计