winform 下拉框(自定义下拉框控件)

  • Post author:
  • Post category:其他


项目中遇到需要下拉框列表内容为线类型或点类型图形的需求,想到可以使用手绘线条和图形的方式来实现下拉列表内容自定义,记录下来供大家参考学习之用。



在项目中添加一个组件

在这里插入图片描述

在这里插入图片描述

添加完之后会显示如下设计界面

在这里插入图片描述

这里直接点击

切换到代码视图

即可

注意:新建的组件默认继承Component,我们这里是要自定义一个ComboBox下拉框,所以要继承自ComboBox,此类位于

using System.Windows.Forms

命名空间下

在这里插入图片描述



线的类型列表

在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CustomComponents
{
    /// <summary>
    /// 填充线型
    /// </summary>
    public partial class FillLineTypeCbo : ComboBox
    {
        public FillLineTypeCbo()
        {
      		//初始化组件
            InitializeComponent();
        }

        public FillLineTypeCbo(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
            InitItems();
        }

        private void InitItems()
        {
            this.DrawMode = DrawMode.OwnerDrawFixed;//手动绘制所有元素
            this.DropDownStyle = ComboBoxStyle.DropDownList;//下拉框样式设置为不能编辑
            this.Items.Clear();//清空原有项 
        }

        public enum LineType
        {
            DoubleHorizontalLine = 0,//双横线
            VerticalLine,//垂直线
            LeftSlash,//左斜线
            RightSlash,//右斜线
            VerticalGridlines,//垂直网格线
            CrossGridlines,//交叉网格线
            SolidBrush,//实心刷
            HollowBrush,//空心刷
        }
        //protected
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (e.Index >= 0)//判断是否需要重绘
            {
                int typeId = int.Parse(this.Items[e.Index].ToString());//获取选项id

                Font font = new Font("宋体", 9);//定义字体
                Rectangle rect = e.Bounds;
                //rect.Inflate(-2, -2);//缩放一定大小
                rect.Inflate(5, -2);//缩放一定大小
                Pen pen = null;
                SolidBrush solidBrush = new SolidBrush(Color.Black);

                float offSet = rect.Height / 2;
                float x = rect.Width / 10;
                float y = rect.Top + offSet;//如果设置成e.ItemHeigh*e.Index +offSet,则在选中节点后,由于Item位置固定,因此Item不能显示出来。
                switch (typeId)
                {
                    case (int)LineType.DoubleHorizontalLine:
                        pen = new Pen(Color.Black, 1);
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(8 * x, y));//绘制水平线
                        e.Graphics.DrawLine(pen, new PointF(x, y + 5), new PointF(8 * x, y + 5));
                        //e.Graphics.DrawLine(pen, new PointF(x, y+2), new PointF(x, y+2));
                        break;
                    case (int)LineType.VerticalLine:
                        pen = new Pen(Color.Black, 1);
                        //绘制垂直线
                        int xNum = 0;
                        for (int i = 0; i < 10; i++)
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNum, y - 4), new PointF(1 * x + xNum, y + 6));
                            xNum += 7;

                        }
                        break;
                    case (int)LineType.LeftSlash:
                        pen = new Pen(Color.Black, 1);
                        //绘制左斜线
                        int xNumLeftSlash = 0;
                        for (int i = 0; i < 10; i++)
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNumLeftSlash, y - 4), new PointF(x + 5 + xNumLeftSlash, y + 7));
                            xNumLeftSlash += 7;
                        }
                        break;
                    case (int)LineType.RightSlash:
                        pen = new Pen(Color.Black, 1);
                        //绘制右斜线
                        int xNumRightSlash = 0;
                        for (int i = 0; i < 10; i++)
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNumRightSlash + 7, y - 4), new PointF(x + xNumRightSlash, y + 7));
                            xNumRightSlash += 7;
                        }
                        break;
                    case (int)LineType.VerticalGridlines:
                        pen = new Pen(Color.Black, 1);
                        //绘制垂直网格线
                        xNum = 0;
                        for (int i = 0; i < 10; i++)//绘制竖线
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNum, y - 4), new PointF(1 * x + xNum, y + 6));
                            xNum += 7;
                        }
                        //绘制双横线
                        e.Graphics.DrawLine(pen, new PointF(x - 3, y - 2), new PointF(8 * x, y - 2));
                        e.Graphics.DrawLine(pen, new PointF(x - 3, y + 5), new PointF(8 * x, y + 5));
                        break;
                    case (int)LineType.CrossGridlines:
                        pen = new Pen(Color.Black, 1);
                        //绘制交叉网格线
                        //绘制左斜线
                        xNumLeftSlash = 0;
                        for (int i = 0; i < 10; i++)
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNumLeftSlash, y - 4), new PointF(x + 10 + xNumLeftSlash, y + 7));
                            xNumLeftSlash += 7;
                        }
                        //绘制右斜线
                        xNumRightSlash = 0;
                        for (int i = 0; i < 10; i++)
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNumRightSlash + 10, y - 4), new PointF(x + xNumRightSlash, y + 7));
                            xNumRightSlash += 7;
                        }
                        break;
                    case (int)LineType.SolidBrush:
                        pen = new Pen(Color.Black, 10);
                        //绘制实心刷
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(8 * x, y));
                        break;
                    case (int)LineType.HollowBrush:
                        pen = new Pen(Color.Black, 1);
                        //绘制空心刷
                        e.Graphics.DrawLine(pen, new PointF(x, y - 6), new PointF(x, y + 6));//左
                        e.Graphics.DrawLine(pen, new PointF(x, y - 6), new PointF(8 * x, y - 6));//上
                        e.Graphics.DrawLine(pen, new PointF(8 * x, y - 6), new PointF(8 * x, y + 6));//右
                        e.Graphics.DrawLine(pen, new PointF(x, y + 6), new PointF(8 * x, y + 6));//下
                        break;
                    default:
                        pen = new Pen(Color.Black, 1);
                        break;
                }
            }
        }
    }
}



边框线类型列表

在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CustomComponents
{
    /// <summary>
    /// 线型
    /// </summary>
    public partial class LineShapeCbo : ComboBox
    {
        public LineShapeCbo()
        {
            InitializeComponent();
        }

        public LineShapeCbo(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
            InitItems();
        }

        private void InitItems()
        {
            this.DrawMode = DrawMode.OwnerDrawFixed;//手动绘制所有元素
            this.DropDownStyle = ComboBoxStyle.DropDownList;//下拉框样式设置为不能编辑
            this.Items.Clear();//清空原有项 
        }

        public enum LineType
        {
            SolidLine = 0,//实线
            LongDisconnection,//长间断线
            ShortEndLine,//短间端线
            LongAndShort,//长短相间
            ShortToLong,//长短短相间
            EmptyBrushes//空画笔
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (e.Index >= 0)//判断是否需要重绘
            {
                int typeId = int.Parse(this.Items[e.Index].ToString());//获取选项id

                Font font = new Font("宋体", 9);//定义字体
                Rectangle rect = e.Bounds;
                //rect.Inflate(-2, -2);//缩放一定大小
                rect.Inflate(5, -2);//缩放一定大小
                Pen pen = null;
                SolidBrush solidBrush = new SolidBrush(Color.Black);

                float offSet = rect.Height / 2;
                float x = rect.Width / 10;
                float y = rect.Top + offSet;//如果设置成e.ItemHeigh*e.Index +offSet,则在选中节点后,由于Item位置固定,因此Item不能显示出来。
                switch (typeId)
                {
                    case (int)LineType.SolidLine:
                        pen = new Pen(Color.Black, 1);
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(8 * x, y));//绘制实线
                        //e.Graphics.DrawLine(pen, new PointF(x, y+2), new PointF(x, y+2));
                        break;
                    case (int)LineType.LongDisconnection:
                        pen = new Pen(Color.Black, 1);
                        //绘制长间断线
                        int xNum = 0;
                        for (int i = 0; i < 3; i++)
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNum, y), new PointF(15+x + xNum, y));
                            xNum += 20;
                        }
                        e.Graphics.DrawLine(pen, new PointF(x + xNum, y), new PointF(10 + x + xNum, y));
                        break;
                    case (int)LineType.ShortEndLine:
                        pen = new Pen(Color.Black, 1);
                        //绘制短间端线
                        xNum = 0;
                        for (int i = 0; i < 8; i++)
                        {
                            e.Graphics.DrawLine(pen, new PointF(x + xNum, y), new PointF(6 + x + xNum, y));
                            xNum += 9;
                        }
                        break;
                    case (int)LineType.LongAndShort:
                        pen = new Pen(Color.Black, 1);
                        //绘制长短相间
                            e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(x+10, y));
                            e.Graphics.DrawLine(pen, new PointF(x+15, y), new PointF(x+20, y));
                            e.Graphics.DrawLine(pen, new PointF(x+25, y), new PointF(x+35, y));
                            e.Graphics.DrawLine(pen, new PointF(x+40, y), new PointF(x+45, y));
                            e.Graphics.DrawLine(pen, new PointF(x+50, y), new PointF(x+60, y));
                            e.Graphics.DrawLine(pen, new PointF(x+65, y), new PointF(x+70, y));
                        break;
                    case (int)LineType.ShortToLong:
                        pen = new Pen(Color.Black, 1);
                        //绘制长短短相间
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(x + 10, y));
                        e.Graphics.DrawLine(pen, new PointF(x+15, y), new PointF(x + 18, y));
                        e.Graphics.DrawLine(pen, new PointF(x+23, y), new PointF(x + 26, y));
                        e.Graphics.DrawLine(pen, new PointF(x+31, y), new PointF(x + 41, y));
                        e.Graphics.DrawLine(pen, new PointF(x + 46, y), new PointF(x + 49, y));
                        e.Graphics.DrawLine(pen, new PointF(x + 54, y), new PointF(x + 57, y));
                        e.Graphics.DrawLine(pen, new PointF(x + 62, y), new PointF(x + 70, y));
                        break;
                    case (int)LineType.EmptyBrushes:
                        pen = new Pen(Color.Black, 1);
                        //绘制空画笔
                        break;
                    //case (int)LineType.LineWithPoints:
                    default:
                        pen = new Pen(Color.Black, 1);
                        break;
                }
                //if (e.Index < 9)
                //{
                //    e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(8 * x, y));//绘制线
                //    //Rectangle rectColor = new Rectangle(rect.Location, new Size(9 * (int)x, rect.Height));
                //    //e.Graphics.DrawRectangle(Pens.Black, rectColor);//绘制边框
                //}
            }
        }
    }
}



点类型列表

在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CustomComponents
{
    /// <summary>
    /// 点类型
    /// </summary>
    public partial class PointTypeCbo : ComboBox
    {
        public PointTypeCbo()
        {
            InitializeComponent();
        }

        public PointTypeCbo(IContainer container)
        {
            container.Add(this);

            InitializeComponent();
            InitItems();
        }
        private void InitItems()
        {
            this.DrawMode = DrawMode.OwnerDrawFixed;//手动绘制所有元素
            this.DropDownStyle = ComboBoxStyle.DropDownList;//下拉框样式设置为不能编辑
            this.Items.Clear();//清空原有项 
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (e.Index >= 0)//判断是否需要重绘
            {
                int typeId = int.Parse(this.Items[e.Index].ToString());//获取选项id

                Font font = new Font("宋体", 9);//定义字体
                Rectangle rect = e.Bounds;
                //rect.Inflate(-2, -2);//缩放一定大小
                rect.Inflate(5, -2);//缩放一定大小
                Pen pen = null;
                SolidBrush solidBrush = new SolidBrush(Color.Black);

                float offSet = rect.Height / 2;
                float x = rect.Width / 10;
                float y = rect.Top + offSet;//如果设置成e.ItemHeigh*e.Index +offSet,则在选中节点后,由于Item位置固定,因此Item不能显示出来。
                switch (typeId)
                {
                    case 0:
                        pen = new Pen(Color.Red, 1);//设置边框
                        //SolidBrush sb0 = new SolidBrush(Color.Black);//设置填充颜色
                        //绘制
                        //e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(8 * x, y));
                        //Graphics g = CreateGraphics();
                        //Brush myBrush = new SolidBrush(Color.Green);
                        //string str = "just for fun";
                        //Font myFont = new Font("宋体", 9, FontStyle.Bold);
                        //e.Graphics.DrawString(str, myFont, myBrush, 60, 20);          
                        //e.Graphics.FillEllipse(sb0, 10 ,10 , 10, 10);
                        e.Graphics.DrawEllipse(pen, 9, 5, 10, 10);
                        break;
                    case 1:
                        pen = new Pen(Color.Red, 1);
                        //绘制正方形
                        e.Graphics.DrawLine(pen, new PointF(x, y - 5), new PointF(x, y + 5));//左
                        e.Graphics.DrawLine(pen, new PointF(x, y - 5), new PointF(x + 10, y - 5));//上
                        e.Graphics.DrawLine(pen, new PointF(x + 10, y - 5), new PointF(x + 10, y + 5));//右
                        e.Graphics.DrawLine(pen, new PointF(x, y + 5), new PointF(x + 10, y + 5));//下

                        //Rectangle rectColor = new Rectangle(rect.Location, new Size(10, 10));
                        //e.Graphics.DrawRectangle(Pens.Black, rectColor);//绘制边框

                        break;
                    case 2:
                        pen = new Pen(Color.Red, 1);
                        //绘制十字形
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(x + 10, y));//横
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y - 5), new PointF(x + 5, y + 5));//竖
                        break;
                    case 3:
                        pen = new Pen(Color.Red, 1);
                        //绘制三角形
                        e.Graphics.DrawLine(pen, new PointF(x, y + 5), new PointF(x + 5, y - 5));//左
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y - 5), new PointF(x + 10, y + 5));//右
                        e.Graphics.DrawLine(pen, new PointF(x, y + 5), new PointF(x + 10, y + 5));//下
                        break;
                    case 4:
                        pen = new Pen(Color.Red, 1);
                        //绘制右(三角)红旗
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y + 5), new PointF(x + 5, y - 5));//竖杆
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y - 5), new PointF(x + 10, y));//红旗右边
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y), new PointF(x + 10, y));//红旗下边
                        break;
                    case 5:
                        pen = new Pen(Color.Red, 1);
                        //绘制左(三角)红旗 
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y + 5), new PointF(x + 5, y - 5));//竖杆
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(x + 5, y - 5));//红旗左边
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(x + 5, y));//红旗下边
                        break;
                    case 6:
                        pen = new Pen(Color.Red, 1);
                        //绘制右方旗
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y + 5), new PointF(x + 5, y - 5));//竖杆
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y - 5), new PointF(x + 10, y - 5));//右上边
                        e.Graphics.DrawLine(pen, new PointF(x + 10, y - 5), new PointF(x + 10, y));//右右边
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y), new PointF(x + 10, y));//右下边
                        break;
                    case 7:
                        pen = new Pen(Color.Red, 1);
                        //绘制大圆包小圆
                        //e.Graphics.DrawEllipse(pen, 20, 115, 10, 10);//空心大圆
                        //e.Graphics.DrawEllipse(pen, 13, 118, 4, 4);//空心小圆 
                        e.Graphics.DrawEllipse(pen, x, y - 5, 10, 10);//空心大圆
                        e.Graphics.DrawEllipse(pen, x + 3, y - 5 + 3, 4, 4);//空心小圆
                        //Rectangle rectColor = new Rectangle(rect.Location, new Size(9 * (int)x, rect.Height));
                        //e.Graphics.DrawRectangle(Pens.Black, rectColor);//绘制边框
                        break;
                    case 8:
                        pen = new Pen(Color.Red, 1);
                        //绘制大圆加十字
                        e.Graphics.DrawEllipse(pen, x, y - 5, 10, 10);//空心大圆
                        //绘制十字形
                        e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(x + 10, y));//横
                        e.Graphics.DrawLine(pen, new PointF(x + 5, y - 5), new PointF(x + 5, y + 5));//竖
                        break;
                    case 9:
                        pen = new Pen(Color.Red, 1);
                        //绘制实心圆
                        SolidBrush sb9 = new SolidBrush(Color.Green);//设置填充颜色
                        e.Graphics.DrawEllipse(pen, x, y - 5, 10, 10);//实心圆边框
                        e.Graphics.FillEllipse(sb9, x, y - 5, 10, 10);//实心圆填充
                        break;
                    case 10:
                        pen = new Pen(Color.Red, 1);
                        //绘制实心正方形
                        //绘制正方形
                        e.Graphics.DrawRectangle(pen, x, y - 5, 10, 10);
                        SolidBrush sb10 = new SolidBrush(Color.Green);//设置填充颜色
                        e.Graphics.FillRectangle(sb10, x, y - 5, 10, 10);
                        break;
                    case 11:
                        pen = new Pen(Color.Red, 1);
                        //绘制
                        PointF p1 = new PointF(x + 5, y - 5);
                        PointF p2 = new PointF(x, y + 5);
                        PointF p3 = new PointF(x + 10, y + 5);
                        PointF[] points = new PointF[3];
                        Brush myBrush = new SolidBrush(Color.Green);
                        points[0] = p1;
                        points[1] = p2;
                        points[2] = p3;
                        e.Graphics.FillPolygon(myBrush, points, FillMode.Alternate);
                        e.Graphics.DrawPolygon(pen, points);
                        break;
                    //case (int)LineType.LineWithPoints:
                    default:
                        pen = new Pen(Color.Black, 1);
                        break;
                }
                if (e.Index < 12)
                {
                    //e.Graphics.DrawLine(pen, new PointF(x, y), new PointF(8 * x, y));//绘制线
                    //设置后面的字符串
                    Rectangle Rect = new Rectangle(rect.Location, new Size(5 * (int)x, rect.Height));

                    //文本内容显示区域
                    Rectangle textRect =
                            new Rectangle(Rect.Right + 2, Rect.Y, e.Bounds.Width - Rect.Width, e.Bounds.Height - 2);

                    //文本格式垂直居中
                    StringFormat strFormat = new StringFormat();
                    strFormat.LineAlignment = StringAlignment.Center;
                    e.Graphics.DrawString((e.Index + 1).ToString(), new Font("微软雅黑", 12), Brushes.Black, textRect, strFormat);
                }
            }
        }
    }
}



带图片的列表

在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ShowState
{
    /// <summary>
    /// 下拉框  下拉列表 图片显示
    /// </summary>
    public partial class ComboBoxImg : ComboBox
    {
        public ComboBoxImg()
        {
            InitializeComponent();
            DrawMode = DrawMode.OwnerDrawFixed;
            DropDownStyle = ComboBoxStyle.DropDownList;
            ItemHeight = 50;
            Width = 40;
        }

        public ComboBoxImg(IContainer container)
        {
            container.Add(this);
            InitializeComponent();

            DrawMode = DrawMode.OwnerDrawFixed;
            DropDownStyle = ComboBoxStyle.DropDownList;
            ItemHeight = 200;
            Width = 40;
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (Items.Count == 0 || e.Index == -1)
                return;
            if ((e.State & DrawItemState.Selected) != 0)
            {
                //渐变画刷
                LinearGradientBrush brush = new LinearGradientBrush(e.Bounds, Color.FromArgb(255, 251, 237),
                                                 Color.FromArgb(255, 236, 181), LinearGradientMode.Vertical);
                //填充区域
                Rectangle borderRect = new Rectangle(3, e.Bounds.Y, e.Bounds.Width - 5, e.Bounds.Height - 2);

                e.Graphics.FillRectangle(brush, borderRect);

                //画边框
                Pen pen = new Pen(Color.FromArgb(229, 195, 101));
                e.Graphics.DrawRectangle(pen, borderRect);
            }
            else
            {
                SolidBrush brush = new SolidBrush(Color.FromArgb(255, 255, 255));
                e.Graphics.FillRectangle(brush, e.Bounds);
            }

            //获得项图片,绘制图片
            ItemEx item = (ItemEx)Items[e.Index];
            Image img = item.Image;

            //图片绘制的区域
            Rectangle imgRect = new Rectangle(6, e.Bounds.Y + 3, 45, 45);
            e.Graphics.DrawImage(img, imgRect);

            //文本内容显示区域
            Rectangle textRect =
                    new Rectangle(imgRect.Right + 2, imgRect.Y, e.Bounds.Width - imgRect.Width, e.Bounds.Height - 2);

            //获得项文本内容,绘制文本
            String itemText = Items[e.Index].ToString();

            //文本格式垂直居中
            StringFormat strFormat = new StringFormat();
            strFormat.LineAlignment = StringAlignment.Center;
            e.Graphics.DrawString(itemText, new Font("微软雅黑", 12), Brushes.Black, textRect, strFormat);
            base.OnDrawItem(e);
        }

    }

    /// <summary>
    /// 下拉框  下拉列表 图片显示
    /// </summary>
    public class ItemEx
    {
        /// <summary>
        /// 图片显示
        /// </summary>
        /// <param name="text">文本</param>
        /// <param name="img">图片(图片路径)</param>
        public ItemEx(string text, Image img)
        {
            Text = text;
            Image = img;
        }

        public string Text { get; set; }
        public Image Image { get; set; }

        public override string ToString()
        {
            return Text;
        }
    }
}



组件编写完之后,进入工具箱,就能看到当前项目中我们自定义的组件了,使用方法跟普通控件方法完全相同,直接拖到窗体即可

在这里插入图片描述



版权声明:本文为pyc_01原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。