.NET中实现自绘的ListBox

在平常的开发过程中,我们为了改善用户的体验,通常会在界面上花一些功夫。因为清爽的界面,通常给用户带来一些耳目一新的感觉,并且能增强用户满意度。前几周的一个项目中,就用到了ListBox,需要突出用户在ListBox中选中的项,而.NET自带的ListBox由于配色过于普通,无法满足我们的需要,这就需要我们重新对ListBox的配色进行一些修改。 在Windows的消息机制中,有一个消息叫做WM_DRAWITEM,当控件(比如:Button,ComboBox,ListBox,Menu)需要被重新绘制的时候,会向该控件的父窗口发送这个消息。父窗口通过响应这个消息,就可以实现对该控件外观的绘制,也就是说,通过响应WM_DRAWITEM消息,我们可以接管系统对控件的绘制,这样,我们就可以随心所欲,用我们喜欢的方式,来绘制这个控件了。听起来不错吧? .NET的WinForm程序,也是基于Windows的GUI界面的窗口,而.NET追溯到最底层,其实也是对Win32 API的更高一个层次的封装。所以,.NET的WinForm程序同样也逃脱不了消息机制。于是我们就可以在程序中,通过设置控件为Owner Draw属性,然后加入对WM_DRAWITEM的处理,就可以在OnDrawItem函数中,定制控件外观了。 理论上就是这样,我们开始动手吧,打造一个具有个性的ListBox控件!需要说明的是,当我们把控件属性中的DrawMode改为OwnerDrawFixed过后,.NET以及将绘制这个控件的责任交给了我们,因此我们必须要实现DrawItem函数,否则ListBox会是一片白,什么也看不到。 1.建立一个简单的工程,在工具箱拖放ListBox到Form上,然后将ListBox属性中的DrawMode改为OwnerDrawFixed,或者在Form_Load中,设置控件的属性: this.listBox1.DrawMode = DrawMode.OwnerDrawFixed; 2.在事件窗口中,为DrawItem添加处理函数。 3.配色方案:这里,我们设定被选中的项目有一个蓝色的外框,并且选中的项中,内容呈亮绿色显示,背景色呈灰色显示,这样就更醒目一些了。 4.最后一步,就是加入OnDrawItem的代码,如下:

private void listBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
    {
        //定义背景色,选中为灰色,未选中为白色
        Brush brNoSelectedBack=Brushes.White;
        Brush brSelectedBack=Brushes.Gray;
        //定义前景色,选中为亮绿色,未选中为黑色
        Brush brSelectedFore=Brushes.LightGreen;
        Brush brNoSelectedFore=Brushes.Black;

        //定义焦点,有焦点状态下绘制蓝色外框(蓝色)
        Pen penFocus=new Pen(Brushes.Blue);


        e.Graphics.FillRectangle(Brushes.White,e.Bounds);

        //绘制Item被选中的情况
        if((e.State & DrawItemState.Selected) == DrawItemState.Selected)
        {
            e.Graphics.FillRectangle(brSelectedBack,e.Bounds);
            //绘制焦点外框
            e.Graphics.DrawRectangle(penFocus,e.Bounds.X,e.Bounds.Y,e.Bounds.Width,e.Bounds.Height-1);
            e.Graphics.DrawString(this.listBox1.Items[e.Index].ToString(),
                                  this.listBox1.Font,brSelectedFore,e.Bounds);
            //e.DrawFocusRectangle();
            return;
        }

        //绘制没有被选中的情况
        e.Graphics.FillRectangle(brNoSelectedBack,e.Bounds);
        e.Graphics.DrawString(this.listBox1.Items[e.Index].ToString(),
                             this.listBox1.Font,brNoSelectedFore,e.Bounds);
    }


  到这里,一个简单的自绘ListBox就实现了,不过这里的代码都是直接加载父窗体的里面,不是很美观。其实我们可以自己实现一个这样的类,并把这个ListBox编译为一个.NET控件,这样,在其他的项目中就可以很简单的重用这个控件了。:)
下面是这个自绘控件的效果,左边是我们的自绘ListBox,右边是普通的ListBox。等有时间,我会把这些封装成为一个dll控件 :)。这里提供源代码的下载,有兴趣的朋友可以再根据自己的需求进行一些自己的修改。

点击下载此文件

支持原创技术分享,据说打赏我的人,都找到了女朋友!