项目中遇到需要下拉框列表内容为线类型或点类型图形的需求,想到可以使用手绘线条和图形的方式来实现下拉列表内容自定义,记录下来供大家参考学习之用。
在项目中添加一个组件
添加完之后会显示如下设计界面
这里直接点击切换到代码视图即可
注意:新建的组件默认继承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;
}
}
}