【Winform-自定义控件】一个自定义的进度条
0.选择基类
public class MySlider : Control
1.设置控件的Style
在构造函数里添加:
public MySlider() { //1.设置控件Style this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); //9.1 }
2.定义变量,并对一些变量进行一些默认设置
//2.定义变量,并对一些变量进行一些默认设置 Rectangle foreRect; Rectangle backRect; Rectangle setRect; Color backgroundColor = Color.White;//背景色 Color foregroundColor = Color.Gray;//已加载颜色 Color setRectColor = Color.Black;//控制块 Color fontColor = Color.Black;//字体颜色 int maximum = 100; //进度条的最大值 int minimum = 0; //进度条的最小值 double myValue = 0;//当前进度值 bool showPercent; //显示当前的百分比 float fontSize = 9;//控件字体的大小 FontFamily myFontFamily = new FontFamily("宋体"); //控件的字体
3.设置属性值
//3.设置属性值 [Category("General"), Description("Show Percent Tag"), Browsable(true)] public bool ShowPercentTag { get { return showPercent; } set { showPercent = value; Invalidate(); } } [Category("General"), Description("Control's Maximum"), Browsable(true)] public int Maximum { get { return maximum; } set { maximum = value; Invalidate(); } } [Category("General"), Description("Control's Minimum"), Browsable(true)] public int Minimum { get { return minimum; } set { minimum = value; Invalidate(); } } [Category("General"), Description("Control's FontSize"), Browsable(true)] public float FontSize { get { return fontSize; } set { this.fontSize = value; Invalidate(); } } [Category("General"), Description("Control's FontFamily"), Browsable(true)] public FontFamily MyFontFamily { get { return myFontFamily; } set { this.myFontFamily = value; Invalidate(); } } [Category("Color"), Browsable(true)] public Color BackgroundColor { get { return backgroundColor; } set { this.backgroundColor = value; Invalidate(); } } [Category("Color"), Browsable(true)] public Color ForegroundColor { get { return foregroundColor; } set { this.foregroundColor = value; Invalidate(); } } [Category("Color"), Browsable(true)] public Color SetRectColor { get { return setRectColor; } set { this.setRectColor = value; Invalidate(); } } [Category("Color"), Browsable(true)] public Color FontColor { get { return fontColor; } set { this.fontColor = value; Invalidate(); } }
4.确定控件的位置
//4.确定控件的位置,我们根据 Width 和 Height 属性来确定矩形的位置,由于Control 类也有这两个属性,我们在前面加上new覆盖掉原有的属性 [Category("General"), Description("Control's Width"), Browsable(true)] public new int Width { get { return base.Width; } set { base.Width = value; foreRect.X = backRect.X = base.Width / 20; backRect.Width = base.Width * 9 / 10; foreRect.Width = (int)(myValue / maximum * backRect.Width); setRect.X = (int)(myValue / maximum * (backRect.Width - backRect.Height) + foreRect.X); Invalidate(); } } [Category("General"), Description("Control's Height"), Browsable(true)] public new int Height { get { return base.Height; } set { base.Height = value; foreRect.Height = backRect.Height = setRect.Height = setRect.Width = base.Height / 3; foreRect.Y = backRect.Y = setRect.Y = base.Height / 3; Invalidate(); } }
5.Value值变化的属性
//5.Value值变化的属性。当外部为该事件添加了响应函数时,事件就会生效,否则为OnValueChanged的值为null protected EventHandler OnValueChanged; public event EventHandler ValueChanged { add { if (OnValueChanged != null) { foreach (Delegate d in OnValueChanged.GetInvocationList()) { if (object.ReferenceEquals(d, value)) { return; } } } OnValueChanged = (EventHandler)Delegate.Combine(OnValueChanged, value); } remove { OnValueChanged = (EventHandler)Delegate.Remove(OnValueChanged, value); } }
6.定义value属性值
//6.定义Value的值。当Value值改变的时候,重新设置矩形的进度,控制块的位置,并且重绘控件 //注意:Value属性内如果对进度条的值进行修改,使用myValue变量,而在其他地方,则用Value属性 [Category("General"), Description("Control's Value"), Browsable(true)] public double Value { get { return myValue; } set { if (myValue < Minimum) throw new ArgumentException("小于最小值"); if (myValue > Maximum) throw new ArgumentException("超过最大值"); myValue = value; foreRect.Width = (int)(myValue / maximum * backRect.Width); setRect.X = (int)(myValue / maximum * (backRect.Width - backRect.Height) + backRect.X); if ((myValue - maximum) > 0) { foreRect.Width = backRect.Width; setRect.X = backRect.Width - backRect.Height + backRect.X; } //如果添加了响应函数,则执行该函数 if (OnValueChanged != null) { OnValueChanged(this, EventArgs.Empty); } Invalidate(); } }
7.绘制控件
//7.绘制控件,重载OnPaint方法对控件进行绘制 protected override void OnPaint(PaintEventArgs pe) { base.OnPaint(pe); DrawRect(pe.Graphics); DrawText(pe.Graphics); } private void DrawRect(Graphics e) { Pen pen = new Pen(this.foregroundColor); e.FillRectangle(new SolidBrush(this.backgroundColor), backRect); e.DrawRectangle(new Pen(Color.Black), backRect); e.FillRectangle(new SolidBrush(this.foregroundColor), foreRect); e.DrawRectangle(new Pen(Color.Black), foreRect); e.FillRectangle(new SolidBrush(this.setRectColor), setRect); e.DrawRectangle(new Pen(Color.Black), setRect); } private void DrawText(Graphics e) { Point point = new Point(); point.X = this.backRect.X + this.backRect.Width * 3 / 7; point.Y = this.backRect.Y + this.backRect.Height / 3; SolidBrush brush = new SolidBrush(fontColor); Font font = new Font(myFontFamily, this.fontSize); string percent = ((int)this.myValue).ToString() + "%"; //通过设置StringFormat可以让文字居中显示 StringFormat format = new StringFormat(); format.Alignment = StringAlignment.Center; format.LineAlignment = StringAlignment.Center; e.DrawString(percent, font, brush, backRect, format); }
8.在设计时,修改控件的大小
//8.最后还有一个方法OnResize,在设计时,修改控件的大小会调用这个方法,比如:拖动边缘的箭头改变控件的大小时,控件也要做相应的改变时,就可以重载该方法,如果没有重载,就只有在修改完成后才更新控件,不懂的可以自己试一下 protected override void OnResize(EventArgs e) { base.OnResize(e); this.Width = Width; this.Height = Height; Invalidate(); }
9.1响应鼠标事件
public MySlider() { //1.设置控件Style //9.1.控件绘制完了,却不能操作,还要对控件进行操作 //通过三个鼠标事件函数,让鼠标可以拖动控制条 this.MouseDown += MySlider_MouseDown; this.MouseMove += MySlider_MouseMove; this.MouseUp += MySlider_MouseUp; }
9.2响应鼠标事件
//9.2.添加三个辅助变量,添加响应函数 Point originPoint; Point originsetRectPoint; bool setRectDown = false; void MySlider_MouseUp(object sender, MouseEventArgs e) { setRectDown = false; } void MySlider_MouseMove(object sender, MouseEventArgs e) { if (setRectDown) { int dd = e.Location.X - originPoint.X; double percent = (double)(originsetRectPoint.X + dd - this.backRect.X) / (this.backRect.Width - this.backRect.Height); if (percent < 0) { this.Value = minimum; this.foreRect.Width = 0; this.setRect.X = backRect.X; } else if (percent > 1) { this.Value = maximum; this.foreRect.Width = this.backRect.Width; this.setRect.X = backRect.X + backRect.Width - backRect.Height; } else { this.Value = percent * maximum; this.foreRect.Width = (int)(percent * this.backRect.Width); this.setRect.X = originsetRectPoint.X + dd; } Invalidate(); } } void MySlider_MouseDown(object sender, MouseEventArgs e) { if (setRect.Contains(e.Location)) { this.originPoint = e.Location; originsetRectPoint = this.setRect.Location; this.setRectDown = true; } }