欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(三十八)c#Winform自定义控件-圆形进度条

程序员文章站 2022-05-29 09:55:44
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果觉得写的还行,请点个 star 支持一下吧 欢迎前来交流探讨: 企鹅群568015492 目录 ......

前提

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

开源地址:

如果觉得写的还行,请点个 star 支持一下吧

欢迎前来交流探讨: 企鹅群568015492 

目录

准备工作

我们理一下思路,进度条支持圆环或扇形显示,支持百分比和数值显示

开始

添加一个用户控件,命名ucprocessellipse

定义2个枚举

 1  public enum valuetype
 2     {
 3         /// <summary>
 4         /// 百分比
 5         /// </summary>
 6         percent,
 7         /// <summary>
 8         /// 数值
 9         /// </summary>
10         absolute
11     }
12 
13     public enum showtype
14     {
15         /// <summary>
16         /// 圆环
17         /// </summary>
18         ring,
19         /// <summary>
20         /// 扇形
21         /// </summary>
22         sector
23     }

 

添加属性

  1  [description("值改变事件"), category("自定义")]
  2         public event eventhandler valuechanged;
  3 
  4         private color m_backellipsecolor = color.fromargb(22, 160, 133);
  5         /// <summary>
  6         /// 圆背景色
  7         /// </summary>
  8         [description("圆背景色"), category("自定义")]
  9         public color backellipsecolor
 10         {
 11             get { return m_backellipsecolor; }
 12             set
 13             {
 14                 m_backellipsecolor = value;
 15                 refresh();
 16             }
 17         }
 18 
 19         private color m_coreellipsecolor = color.fromargb(180, 180, 180);
 20         /// <summary>
 21         /// 内圆颜色,showtype=ring 有效
 22         /// </summary>
 23         [description("内圆颜色,showtype=ring 有效"), category("自定义")]
 24         public color coreellipsecolor
 25         {
 26             get { return m_coreellipsecolor; }
 27             set
 28             {
 29                 m_coreellipsecolor = value;
 30                 refresh();
 31             }
 32         }
 33 
 34         private color m_valuecolor = color.fromargb(255, 77, 59);
 35 
 36         [description("值圆颜色"), category("自定义")]
 37         public color valuecolor
 38         {
 39             get { return m_valuecolor; }
 40             set
 41             {
 42                 m_valuecolor = value;
 43                 refresh();
 44             }
 45         }
 46 
 47         private bool m_isshowcoreellipseborder = true;
 48         /// <summary>
 49         /// 内圆是否显示边框,showtype=ring 有效
 50         /// </summary>
 51         [description("内圆是否显示边框,showtype=ring 有效"), category("自定义")]
 52         public bool isshowcoreellipseborder
 53         {
 54             get { return m_isshowcoreellipseborder; }
 55             set
 56             {
 57                 m_isshowcoreellipseborder = value;
 58                 refresh();
 59             }
 60         }
 61 
 62         private valuetype m_valuetype = valuetype.percent;
 63         /// <summary>
 64         /// 值文字类型
 65         /// </summary>
 66         [description("值文字类型"), category("自定义")]
 67         public valuetype valuetype
 68         {
 69             get { return m_valuetype; }
 70             set
 71             {
 72                 m_valuetype = value;
 73                 refresh();
 74             }
 75         }
 76 
 77         private int m_valuewidth = 30;
 78         /// <summary>
 79         /// 外圆值宽度
 80         /// </summary>
 81         [description("外圆值宽度,showtype=ring 有效"), category("自定义")]
 82         public int valuewidth
 83         {
 84             get { return m_valuewidth; }
 85             set
 86             {
 87                 if (value <= 0 || value > math.min(this.width, this.height))
 88                     return;
 89                 m_valuewidth = value;
 90                 refresh();
 91             }
 92         }
 93 
 94         private int m_valuemargin = 5;
 95         /// <summary>
 96         /// 外圆值间距
 97         /// </summary>
 98         [description("外圆值间距"), category("自定义")]
 99         public int valuemargin
100         {
101             get { return m_valuemargin; }
102             set
103             {
104                 if (value < 0 || m_valuemargin >= m_valuewidth)
105                     return;
106                 m_valuemargin = value;
107                 refresh();
108             }
109         }
110 
111         private int m_maxvalue = 100;
112         /// <summary>
113         /// 最大值
114         /// </summary>
115         [description("最大值"), category("自定义")]
116         public int maxvalue
117         {
118             get { return m_maxvalue; }
119             set
120             {
121                 if (value > m_value || value <= 0)
122                     return;
123                 m_maxvalue = value;
124                 refresh();
125             }
126         }
127 
128         private int m_value = 0;
129         /// <summary>
130         /// 当前值
131         /// </summary>
132         [description("当前值"), category("自定义")]
133         public int value
134         {
135             get { return m_value; }
136             set
137             {
138                 if (m_maxvalue < value || value <= 0)
139                     return;
140                 m_value = value;
141                 if (valuechanged != null)
142                 {
143                     valuechanged(this, null);
144                 }
145                 refresh();
146             }
147         }
148         private font m_font = new font("arial unicode ms", 20);
149         [description("文字字体"), category("自定义")]
150         public override font font
151         {
152             get
153             {
154                 return m_font;
155             }
156             set
157             {
158                 m_font = value;
159                 refresh();
160             }
161         }
162         color m_forecolor = color.white;
163         [description("文字颜色"), category("自定义")]
164         public override color forecolor
165         {
166             get
167             {
168                 return m_forecolor;
169             }
170             set
171             {
172                 m_forecolor = value;
173                 refresh();
174             }
175         }
176 
177         private showtype m_showtype = showtype.ring;
178 
179         [description("显示类型"), category("自定义")]
180         public showtype showtype
181         {
182             get { return m_showtype; }
183             set
184             {
185                 m_showtype = value;
186                 refresh();
187             }
188         }

重绘

 1   protected override void onpaint(painteventargs e)
 2         {
 3             base.onpaint(e);
 4 
 5             var g = e.graphics;
 6             g.smoothingmode = smoothingmode.antialias;  //使绘图质量最高,即消除锯齿
 7             g.interpolationmode = interpolationmode.highqualitybicubic;
 8             g.compositingquality = compositingquality.highquality;
 9 
10             int intwidth = math.min(this.size.width, this.size.height);
11             //底圆
12             g.fillellipse(new solidbrush(m_backellipsecolor), new rectangle(new point(0, 0), new size(intwidth, intwidth)));
13             if (m_showtype == hzh_controls.controls.showtype.ring)
14             {
15                 //中心圆
16                 int intcore = intwidth - m_valuewidth * 2;
17                 g.fillellipse(new solidbrush(m_coreellipsecolor), new rectangle(new point(m_valuewidth, m_valuewidth), new size(intcore, intcore)));
18                 //中心圆边框
19                 if (m_isshowcoreellipseborder)
20                 {
21                     g.drawellipse(new pen(m_valuecolor, 2), new rectangle(new point(m_valuewidth + 1, m_valuewidth + 1), new size(intcore - 1, intcore - 1)));
22                 }
23                 if (m_value > 0 && m_maxvalue > 0)
24                 {
25                     float fltpercent = (float)m_value / (float)m_maxvalue;
26                     if (fltpercent > 1)
27                     {
28                         fltpercent = 1;
29                     }
30 
31                     g.drawarc(new pen(m_valuecolor, m_valuewidth - m_valuemargin * 2), new rectanglef(new point(m_valuewidth / 2 + m_valuemargin / 4, m_valuewidth / 2 + m_valuemargin / 4), new sizef(intwidth - m_valuewidth - m_valuemargin / 2 + (m_valuemargin == 0 ? 0 : 1), intwidth - m_valuewidth - m_valuemargin / 2 + (m_valuemargin == 0 ? 0 : 1))), -90, fltpercent * 360);
32 
33                     string strvaluetext = m_valuetype == hzh_controls.controls.valuetype.percent ? fltpercent.tostring("0%") : m_value.tostring();
34                     system.drawing.sizef _txtsize = g.measurestring(strvaluetext, this.font);
35                     g.drawstring(strvaluetext, this.font, new solidbrush(this.forecolor), new pointf((intwidth - _txtsize.width) / 2 + 1, (intwidth - _txtsize.height) / 2 + 1));
36                 }
37             }
38             else
39             {
40                 if (m_value > 0 && m_maxvalue > 0)
41                 {
42                     float fltpercent = (float)m_value / (float)m_maxvalue;
43                     if (fltpercent > 1)
44                     {
45                         fltpercent = 1;
46                     }
47 
48                     g.fillpie(new solidbrush(m_valuecolor), new rectangle(m_valuemargin, m_valuemargin, intwidth - m_valuemargin * 2, intwidth - m_valuemargin * 2), -90, fltpercent * 360);
49 
50                     string strvaluetext = m_valuetype == hzh_controls.controls.valuetype.percent ? fltpercent.tostring("0%") : m_value.tostring();
51                     system.drawing.sizef _txtsize = g.measurestring(strvaluetext, this.font);
52                     g.drawstring(strvaluetext, this.font, new solidbrush(this.forecolor), new pointf((intwidth - _txtsize.width) / 2 + 1, (intwidth - _txtsize.height) / 2 + 1));
53                 }
54             }
55 
56         }

完整代码如下

  1 using system;
  2 using system.collections.generic;
  3 using system.componentmodel;
  4 using system.drawing;
  5 using system.data;
  6 using system.linq;
  7 using system.text;
  8 using system.windows.forms;
  9 using system.drawing.drawing2d;
 10 
 11 namespace hzh_controls.controls
 12 {
 13     public partial class ucprocessellipse : usercontrol
 14     {
 15         [description("值改变事件"), category("自定义")]
 16         public event eventhandler valuechanged;
 17 
 18         private color m_backellipsecolor = color.fromargb(22, 160, 133);
 19         /// <summary>
 20         /// 圆背景色
 21         /// </summary>
 22         [description("圆背景色"), category("自定义")]
 23         public color backellipsecolor
 24         {
 25             get { return m_backellipsecolor; }
 26             set
 27             {
 28                 m_backellipsecolor = value;
 29                 refresh();
 30             }
 31         }
 32 
 33         private color m_coreellipsecolor = color.fromargb(180, 180, 180);
 34         /// <summary>
 35         /// 内圆颜色,showtype=ring 有效
 36         /// </summary>
 37         [description("内圆颜色,showtype=ring 有效"), category("自定义")]
 38         public color coreellipsecolor
 39         {
 40             get { return m_coreellipsecolor; }
 41             set
 42             {
 43                 m_coreellipsecolor = value;
 44                 refresh();
 45             }
 46         }
 47 
 48         private color m_valuecolor = color.fromargb(255, 77, 59);
 49 
 50         [description("值圆颜色"), category("自定义")]
 51         public color valuecolor
 52         {
 53             get { return m_valuecolor; }
 54             set
 55             {
 56                 m_valuecolor = value;
 57                 refresh();
 58             }
 59         }
 60 
 61         private bool m_isshowcoreellipseborder = true;
 62         /// <summary>
 63         /// 内圆是否显示边框,showtype=ring 有效
 64         /// </summary>
 65         [description("内圆是否显示边框,showtype=ring 有效"), category("自定义")]
 66         public bool isshowcoreellipseborder
 67         {
 68             get { return m_isshowcoreellipseborder; }
 69             set
 70             {
 71                 m_isshowcoreellipseborder = value;
 72                 refresh();
 73             }
 74         }
 75 
 76         private valuetype m_valuetype = valuetype.percent;
 77         /// <summary>
 78         /// 值文字类型
 79         /// </summary>
 80         [description("值文字类型"), category("自定义")]
 81         public valuetype valuetype
 82         {
 83             get { return m_valuetype; }
 84             set
 85             {
 86                 m_valuetype = value;
 87                 refresh();
 88             }
 89         }
 90 
 91         private int m_valuewidth = 30;
 92         /// <summary>
 93         /// 外圆值宽度
 94         /// </summary>
 95         [description("外圆值宽度,showtype=ring 有效"), category("自定义")]
 96         public int valuewidth
 97         {
 98             get { return m_valuewidth; }
 99             set
100             {
101                 if (value <= 0 || value > math.min(this.width, this.height))
102                     return;
103                 m_valuewidth = value;
104                 refresh();
105             }
106         }
107 
108         private int m_valuemargin = 5;
109         /// <summary>
110         /// 外圆值间距
111         /// </summary>
112         [description("外圆值间距"), category("自定义")]
113         public int valuemargin
114         {
115             get { return m_valuemargin; }
116             set
117             {
118                 if (value < 0 || m_valuemargin >= m_valuewidth)
119                     return;
120                 m_valuemargin = value;
121                 refresh();
122             }
123         }
124 
125         private int m_maxvalue = 100;
126         /// <summary>
127         /// 最大值
128         /// </summary>
129         [description("最大值"), category("自定义")]
130         public int maxvalue
131         {
132             get { return m_maxvalue; }
133             set
134             {
135                 if (value > m_value || value <= 0)
136                     return;
137                 m_maxvalue = value;
138                 refresh();
139             }
140         }
141 
142         private int m_value = 0;
143         /// <summary>
144         /// 当前值
145         /// </summary>
146         [description("当前值"), category("自定义")]
147         public int value
148         {
149             get { return m_value; }
150             set
151             {
152                 if (m_maxvalue < value || value <= 0)
153                     return;
154                 m_value = value;
155                 if (valuechanged != null)
156                 {
157                     valuechanged(this, null);
158                 }
159                 refresh();
160             }
161         }
162         private font m_font = new font("arial unicode ms", 20);
163         [description("文字字体"), category("自定义")]
164         public override font font
165         {
166             get
167             {
168                 return m_font;
169             }
170             set
171             {
172                 m_font = value;
173                 refresh();
174             }
175         }
176         color m_forecolor = color.white;
177         [description("文字颜色"), category("自定义")]
178         public override color forecolor
179         {
180             get
181             {
182                 return m_forecolor;
183             }
184             set
185             {
186                 m_forecolor = value;
187                 refresh();
188             }
189         }
190 
191         private showtype m_showtype = showtype.ring;
192 
193         [description("显示类型"), category("自定义")]
194         public showtype showtype
195         {
196             get { return m_showtype; }
197             set
198             {
199                 m_showtype = value;
200                 refresh();
201             }
202         }
203 
204         public ucprocessellipse()
205         {
206             initializecomponent();
207             this.setstyle(controlstyles.allpaintinginwmpaint, true);
208             this.setstyle(controlstyles.doublebuffer, true);
209             this.setstyle(controlstyles.resizeredraw, true);
210             this.setstyle(controlstyles.selectable, true);
211             this.setstyle(controlstyles.supportstransparentbackcolor, true);
212             this.setstyle(controlstyles.userpaint, true);
213         }
214 
215         protected override void onpaint(painteventargs e)
216         {
217             base.onpaint(e);
218 
219             var g = e.graphics;
220             g.smoothingmode = smoothingmode.antialias;  //使绘图质量最高,即消除锯齿
221             g.interpolationmode = interpolationmode.highqualitybicubic;
222             g.compositingquality = compositingquality.highquality;
223 
224             int intwidth = math.min(this.size.width, this.size.height);
225             //底圆
226             g.fillellipse(new solidbrush(m_backellipsecolor), new rectangle(new point(0, 0), new size(intwidth, intwidth)));
227             if (m_showtype == hzh_controls.controls.showtype.ring)
228             {
229                 //中心圆
230                 int intcore = intwidth - m_valuewidth * 2;
231                 g.fillellipse(new solidbrush(m_coreellipsecolor), new rectangle(new point(m_valuewidth, m_valuewidth), new size(intcore, intcore)));
232                 //中心圆边框
233                 if (m_isshowcoreellipseborder)
234                 {
235                     g.drawellipse(new pen(m_valuecolor, 2), new rectangle(new point(m_valuewidth + 1, m_valuewidth + 1), new size(intcore - 1, intcore - 1)));
236                 }
237                 if (m_value > 0 && m_maxvalue > 0)
238                 {
239                     float fltpercent = (float)m_value / (float)m_maxvalue;
240                     if (fltpercent > 1)
241                     {
242                         fltpercent = 1;
243                     }
244 
245                     g.drawarc(new pen(m_valuecolor, m_valuewidth - m_valuemargin * 2), new rectanglef(new point(m_valuewidth / 2 + m_valuemargin / 4, m_valuewidth / 2 + m_valuemargin / 4), new sizef(intwidth - m_valuewidth - m_valuemargin / 2 + (m_valuemargin == 0 ? 0 : 1), intwidth - m_valuewidth - m_valuemargin / 2 + (m_valuemargin == 0 ? 0 : 1))), -90, fltpercent * 360);
246 
247                     string strvaluetext = m_valuetype == hzh_controls.controls.valuetype.percent ? fltpercent.tostring("0%") : m_value.tostring();
248                     system.drawing.sizef _txtsize = g.measurestring(strvaluetext, this.font);
249                     g.drawstring(strvaluetext, this.font, new solidbrush(this.forecolor), new pointf((intwidth - _txtsize.width) / 2 + 1, (intwidth - _txtsize.height) / 2 + 1));
250                 }
251             }
252             else
253             {
254                 if (m_value > 0 && m_maxvalue > 0)
255                 {
256                     float fltpercent = (float)m_value / (float)m_maxvalue;
257                     if (fltpercent > 1)
258                     {
259                         fltpercent = 1;
260                     }
261 
262                     g.fillpie(new solidbrush(m_valuecolor), new rectangle(m_valuemargin, m_valuemargin, intwidth - m_valuemargin * 2, intwidth - m_valuemargin * 2), -90, fltpercent * 360);
263 
264                     string strvaluetext = m_valuetype == hzh_controls.controls.valuetype.percent ? fltpercent.tostring("0%") : m_value.tostring();
265                     system.drawing.sizef _txtsize = g.measurestring(strvaluetext, this.font);
266                     g.drawstring(strvaluetext, this.font, new solidbrush(this.forecolor), new pointf((intwidth - _txtsize.width) / 2 + 1, (intwidth - _txtsize.height) / 2 + 1));
267                 }
268             }
269 
270         }
271     }
272 
273     public enum valuetype
274     {
275         /// <summary>
276         /// 百分比
277         /// </summary>
278         percent,
279         /// <summary>
280         /// 数值
281         /// </summary>
282         absolute
283     }
284 
285     public enum showtype
286     {
287         /// <summary>
288         /// 圆环
289         /// </summary>
290         ring,
291         /// <summary>
292         /// 扇形
293         /// </summary>
294         sector
295     }
296 }
 1 namespace hzh_controls.controls
 2 {
 3     partial class ucprocessellipse
 4     {
 5         /// <summary> 
 6         /// 必需的设计器变量。
 7         /// </summary>
 8         private system.componentmodel.icontainer components = null;
 9 
10         /// <summary> 
11         /// 清理所有正在使用的资源。
12         /// </summary>
13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
14         protected override void dispose(bool disposing)
15         {
16             if (disposing && (components != null))
17             {
18                 components.dispose();
19             }
20             base.dispose(disposing);
21         }
22 
23         #region 组件设计器生成的代码
24 
25         /// <summary> 
26         /// 设计器支持所需的方法 - 不要
27         /// 使用代码编辑器修改此方法的内容。
28         /// </summary>
29         private void initializecomponent()
30         {
31             components = new system.componentmodel.container();
32             this.autoscalemode = system.windows.forms.autoscalemode.font;
33         }
34 
35         #endregion
36     }
37 }

用处及效果

(三十八)c#Winform自定义控件-圆形进度条

(三十八)c#Winform自定义控件-圆形进度条

最后的话

如果你喜欢的话,请到  点个星 星吧