(四十六)c#Winform自定义控件-水波进度条
·
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
官网:https://www.hzhcontrols.cn
GitHub:https://github.com/kwwwvagaa/NetWinformControl
如果觉得写的还行,请点个 star 支持一下吧
麻烦博客下方点个【推荐】,谢谢
NuGet
Install-Package HZH_Controls
目录
c#Winform自定义控件-目录_c#winform自定义控件-有图标的按钮-CSDN博客
用处及效果

准备工作
这个用到GDI+画的,请先了解一下GDI+
还有用到了基类控件UCControlBase来控制圆角和背景色,如果还不了解请移步查看
另外用到了水波控件UCWave,如果不了解请移步查看
开始
添加一个用户控件UCProcessWave,继承UCControlBase
一些属性

1 private bool m_isRectangle = false;
2 [Description("是否矩形"), Category("自定义")]
3 public bool IsRectangle
4 {
5 get { return m_isRectangle; }
6 set
7 {
8 m_isRectangle = value;
9 if (value)
10 {
11 base.ConerRadius = 10;
12 }
13 else
14 {
15 base.ConerRadius = Math.Min(this.Width, this.Height);
16 }
17 }
18 }
19 #region 不再使用的父类属性 English:Parent class attributes that are no longer used
20 [Browsable(false)]
21 public new int ConerRadius
22 {
23 get;
24 set;
25 }
26 [Browsable(false)]
27 public new bool IsRadius
28 {
29 get;
30 set;
31 }
32
33 [Browsable(false)]
34 public new Color FillColor
35 {
36 get;
37 set;
38 }
39 #endregion
40
41
42 [Description("值变更事件"), Category("自定义")]
43 public event EventHandler ValueChanged;
44 int m_value = 0;
45 [Description("当前属性"), Category("自定义")]
46 public int Value
47 {
48 set
49 {
50 if (value > m_maxValue)
51 m_value = m_maxValue;
52 else if (value < 0)
53 m_value = 0;
54 else
55 m_value = value;
56 if (ValueChanged != null)
57 ValueChanged(this, null);
58 ucWave1.Height = (int)((double)m_value / (double)m_maxValue * this.Height) + ucWave1.WaveHeight;
59 Refresh();
60 }
61 get
62 {
63 return m_value;
64 }
65 }
66
67 private int m_maxValue = 100;
68
69 [Description("最大值"), Category("自定义")]
70 public int MaxValue
71 {
72 get { return m_maxValue; }
73 set
74 {
75 if (value < m_value)
76 m_maxValue = m_value;
77 else
78 m_maxValue = value;
79 Refresh();
80 }
81 }
82
83 public override Font Font
84 {
85 get
86 {
87 return base.Font;
88 }
89 set
90 {
91 base.Font = value;
92 }
93 }
94
95 public override Color ForeColor
96 {
97 get
98 {
99 return base.ForeColor;
100 }
101 set
102 {
103 base.ForeColor = value;
104 }
105 }
106
107 [Description("值颜色"), Category("自定义")]
108 public Color ValueColor
109 {
110 get { return this.ucWave1.WaveColor; }
111 set
112 {
113 this.ucWave1.WaveColor = value;
114 }
115 }
116
117 [Description("边框宽度"), Category("自定义")]
118 public override int RectWidth
119 {
120 get
121 {
122 return base.RectWidth;
123 }
124 set
125 {
126 if (value < 4)
127 base.RectWidth = 4;
128 else
129 base.RectWidth = value;
130 }
131 }

构造函数一些设置

1 public UCProcessWave()
2 {
3 InitializeComponent();
4 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
5 this.SetStyle(ControlStyles.DoubleBuffer, true);
6 this.SetStyle(ControlStyles.ResizeRedraw, true);
7 this.SetStyle(ControlStyles.Selectable, true);
8 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
9 this.SetStyle(ControlStyles.UserPaint, true);
10 base.IsRadius = true;
11 base.IsShowRect = false;
12 RectWidth = 4;
13 RectColor = Color.White;
14 ucWave1.Height = (int)((double)m_value / (double)m_maxValue * this.Height) + ucWave1.WaveHeight;
15 this.SizeChanged += UCProcessWave_SizeChanged;
16 this.ucWave1.OnPainted += ucWave1_Painted;
17 base.ConerRadius = Math.Min(this.Width, this.Height);
18 }

重绘

1 protected override void OnPaint(PaintEventArgs e)
2 {
3 base.OnPaint(e);
4 e.Graphics.SetGDIHigh();
5 if (!m_isRectangle)
6 {
7 //这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
8 SolidBrush solidBrush = new SolidBrush(Color.White);
9 e.Graphics.DrawEllipse(new Pen(solidBrush, 2), new Rectangle(-1, -1, this.Width + 2, this.Height + 2));
10 }
11 string strValue = ((double)m_value / (double)m_maxValue).ToString("0.%");
12 System.Drawing.SizeF sizeF = e.Graphics.MeasureString(strValue, Font);
13 e.Graphics.DrawString(strValue, Font, new SolidBrush(ForeColor), new PointF((this.Width - sizeF.Width) / 2, (this.Height - sizeF.Height) / 2 + 1));
14 }

波形控件重绘时处理

1 void ucWave1_Painted(object sender, PaintEventArgs e)
2 {
3 e.Graphics.SetGDIHigh();
4 if (IsShowRect)
5 {
6 if (m_isRectangle)
7 {
8 Color rectColor = RectColor;
9 Pen pen = new Pen(rectColor, (float)RectWidth);
10 Rectangle clientRectangle = new Rectangle(0, this.ucWave1.Height - this.Height, this.Width, this.Height);
11 GraphicsPath graphicsPath = new GraphicsPath();
12 graphicsPath.AddArc(clientRectangle.X, clientRectangle.Y, 10, 10, 180f, 90f);
13 graphicsPath.AddArc(clientRectangle.Width - 10 - 1, clientRectangle.Y, 10, 10, 270f, 90f);
14 graphicsPath.AddArc(clientRectangle.Width - 10 - 1, clientRectangle.Bottom - 10 - 1, 10, 10, 0f, 90f);
15 graphicsPath.AddArc(clientRectangle.X, clientRectangle.Bottom - 10 - 1, 10, 10, 90f, 90f);
16 graphicsPath.CloseFigure();
17 e.Graphics.DrawPath(pen, graphicsPath);
18 }
19 else
20 {
21 SolidBrush solidBrush = new SolidBrush(RectColor);
22 e.Graphics.DrawEllipse(new Pen(solidBrush, RectWidth), new Rectangle(0, this.ucWave1.Height - this.Height, this.Width, this.Height));
23 }
24 }
25
26 if (!m_isRectangle)
27 {
28 //这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
29 SolidBrush solidBrush1 = new SolidBrush(Color.White);
30 e.Graphics.DrawEllipse(new Pen(solidBrush1, 2), new Rectangle(-1, this.ucWave1.Height - this.Height - 1, this.Width + 2, this.Height + 2));
31 }
32 string strValue = ((double)m_value / (double)m_maxValue).ToString("0.%");
33 System.Drawing.SizeF sizeF = e.Graphics.MeasureString(strValue, Font);
34 e.Graphics.DrawString(strValue, Font, new SolidBrush(ForeColor), new PointF((this.Width - sizeF.Width) / 2, (this.ucWave1.Height - this.Height) + (this.Height - sizeF.Height) / 2));
35 }

不知道你们有没有注意这句话
//这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
因为设置原价导致了区域毛边,所有画个没有毛边的边框覆盖之
完整代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace HZH_Controls.Controls
{
public partial class UCProcessWave : UCControlBase
{
private bool m_isRectangle = false;
[Description("是否矩形"), Category("自定义")]
public bool IsRectangle
{
get { return m_isRectangle; }
set
{
m_isRectangle = value;
if (value)
{
base.ConerRadius = 10;
}
else
{
base.ConerRadius = Math.Min(this.Width, this.Height);
}
}
}
#region 不再使用的父类属性 English:Parent class attributes that are no longer used
[Browsable(false)]
public new int ConerRadius
{
get;
set;
}
[Browsable(false)]
public new bool IsRadius
{
get;
set;
}
[Browsable(false)]
public new Color FillColor
{
get;
set;
}
#endregion
[Description("值变更事件"), Category("自定义")]
public event EventHandler ValueChanged;
int m_value = 0;
[Description("当前属性"), Category("自定义")]
public int Value
{
set
{
if (value > m_maxValue)
m_value = m_maxValue;
else if (value < 0)
m_value = 0;
else
m_value = value;
if (ValueChanged != null)
ValueChanged(this, null);
ucWave1.Height = (int)((double)m_value / (double)m_maxValue * this.Height) + ucWave1.WaveHeight;
Refresh();
}
get
{
return m_value;
}
}
private int m_maxValue = 100;
[Description("最大值"), Category("自定义")]
public int MaxValue
{
get { return m_maxValue; }
set
{
if (value < m_value)
m_maxValue = m_value;
else
m_maxValue = value;
Refresh();
}
}
public override Font Font
{
get
{
return base.Font;
}
set
{
base.Font = value;
}
}
public override Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
base.ForeColor = value;
}
}
[Description("值颜色"), Category("自定义")]
public Color ValueColor
{
get { return this.ucWave1.WaveColor; }
set
{
this.ucWave1.WaveColor = value;
}
}
[Description("边框宽度"), Category("自定义")]
public override int RectWidth
{
get
{
return base.RectWidth;
}
set
{
if (value < 4)
base.RectWidth = 4;
else
base.RectWidth = value;
}
}
public UCProcessWave()
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
base.IsRadius = true;
base.IsShowRect = false;
RectWidth = 4;
RectColor = Color.White;
ucWave1.Height = (int)((double)m_value / (double)m_maxValue * this.Height) + ucWave1.WaveHeight;
this.SizeChanged += UCProcessWave_SizeChanged;
this.ucWave1.OnPainted += ucWave1_Painted;
base.ConerRadius = Math.Min(this.Width, this.Height);
}
void ucWave1_Painted(object sender, PaintEventArgs e)
{
e.Graphics.SetGDIHigh();
if (IsShowRect)
{
if (m_isRectangle)
{
Color rectColor = RectColor;
Pen pen = new Pen(rectColor, (float)RectWidth);
Rectangle clientRectangle = new Rectangle(0, this.ucWave1.Height - this.Height, this.Width, this.Height);
GraphicsPath graphicsPath = new GraphicsPath();
graphicsPath.AddArc(clientRectangle.X, clientRectangle.Y, 10, 10, 180f, 90f);
graphicsPath.AddArc(clientRectangle.Width - 10 - 1, clientRectangle.Y, 10, 10, 270f, 90f);
graphicsPath.AddArc(clientRectangle.Width - 10 - 1, clientRectangle.Bottom - 10 - 1, 10, 10, 0f, 90f);
graphicsPath.AddArc(clientRectangle.X, clientRectangle.Bottom - 10 - 1, 10, 10, 90f, 90f);
graphicsPath.CloseFigure();
e.Graphics.DrawPath(pen, graphicsPath);
}
else
{
SolidBrush solidBrush = new SolidBrush(RectColor);
e.Graphics.DrawEllipse(new Pen(solidBrush, RectWidth), new Rectangle(0, this.ucWave1.Height - this.Height, this.Width, this.Height));
}
}
if (!m_isRectangle)
{
//这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
SolidBrush solidBrush1 = new SolidBrush(Color.White);
e.Graphics.DrawEllipse(new Pen(solidBrush1, 2), new Rectangle(-1, this.ucWave1.Height - this.Height - 1, this.Width + 2, this.Height + 2));
}
string strValue = ((double)m_value / (double)m_maxValue).ToString("0.%");
System.Drawing.SizeF sizeF = e.Graphics.MeasureString(strValue, Font);
e.Graphics.DrawString(strValue, Font, new SolidBrush(ForeColor), new PointF((this.Width - sizeF.Width) / 2, (this.ucWave1.Height - this.Height) + (this.Height - sizeF.Height) / 2));
}
void UCProcessWave_SizeChanged(object sender, EventArgs e)
{
if (!m_isRectangle)
{
base.ConerRadius = Math.Min(this.Width, this.Height);
if (this.Width != this.Height)
{
this.Size = new Size(Math.Min(this.Width, this.Height), Math.Min(this.Width, this.Height));
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SetGDIHigh();
if (!m_isRectangle)
{
//这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
SolidBrush solidBrush = new SolidBrush(Color.White);
e.Graphics.DrawEllipse(new Pen(solidBrush, 2), new Rectangle(-1, -1, this.Width + 2, this.Height + 2));
}
string strValue = ((double)m_value / (double)m_maxValue).ToString("0.%");
System.Drawing.SizeF sizeF = e.Graphics.MeasureString(strValue, Font);
e.Graphics.DrawString(strValue, Font, new SolidBrush(ForeColor), new PointF((this.Width - sizeF.Width) / 2, (this.Height - sizeF.Height) / 2 + 1));
}
}
}
namespace HZH_Controls.Controls
{
partial class UCProcessWave
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.ucWave1 = new HZH_Controls.Controls.UCWave();
this.SuspendLayout();
//
// ucWave1
//
this.ucWave1.Dock = System.Windows.Forms.DockStyle.Bottom;
this.ucWave1.Location = new System.Drawing.Point(0, 140);
this.ucWave1.Name = "ucWave1";
this.ucWave1.Size = new System.Drawing.Size(150, 10);
this.ucWave1.TabIndex = 0;
this.ucWave1.Text = "ucWave1";
this.ucWave1.WaveColor = System.Drawing.Color.FromArgb(((int)(((byte)(73)))), ((int)(((byte)(119)))), ((int)(((byte)(232)))));
this.ucWave1.WaveHeight = 15;
this.ucWave1.WaveSleep = 100;
this.ucWave1.WaveWidth = 100;
//
// UCProcessWave
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(197)))), ((int)(((byte)(229)))), ((int)(((byte)(250)))));
this.Controls.Add(this.ucWave1);
this.Name = "UCProcessWave";
this.Size = new System.Drawing.Size(150, 150);
this.ResumeLayout(false);
}
#endregion
private UCWave ucWave1;
}
}
最后的话
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)