前提

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

github:https://github.com/kwwwvagaa/netwinformcontrol

码云:

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

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

麻烦博客下方点个【推荐】,谢谢

nuget

install-package hzh_controls

目录

用处及效果

准备工作

这个用到gdi+画的,请先了解一下gdi+

还有用到了基类控件uccontrolbase来控制圆角和背景色,如果还不了解请移步查看

(一)c#winform自定义控件-基类控件

另外用到了水波控件ucwave,如果不了解请移步查看

(四十四)c#winform自定义控件-水波

开始

添加一个用户控件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         }

不知道你们有没有注意这句话

 //这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡

因为设置原价导致了区域毛边,所有画个没有毛边的边框覆盖之

 

完整代码

  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 ucprocesswave : uccontrolbase
14     {
15         private bool m_isrectangle = false;
16         [description("是否矩形"), category("自定义")]
17         public bool isrectangle
18         {
19             get { return m_isrectangle; }
20             set
21             {
22                 m_isrectangle = value;
23                 if (value)
24                 {
25                     base.conerradius = 10;
26                 }
27                 else
28                 {
29                     base.conerradius = math.min(this.width, this.height);
30                 }
31             }
32         }
33         #region 不再使用的父类属性    english:parent class attributes that are no longer used
34         [browsable(false)]
35         public new int conerradius
36         {
37             get;
38             set;
39         }
40         [browsable(false)]
41         public new bool isradius
42         {
43             get;
44             set;
45         }
46 
47         [browsable(false)]
48         public new color fillcolor
49         {
50             get;
51             set;
52         }
53         #endregion
54 
55 
56         [description("值变更事件"), category("自定义")]
57         public event eventhandler valuechanged;
58         int m_value = 0;
59         [description("当前属性"), category("自定义")]
60         public int value
61         {
62             set
63             {
64                 if (value > m_maxvalue)
65                     m_value = m_maxvalue;
66                 else if (value < 0)
67                     m_value = 0;
68                 else
69                     m_value = value;
70                 if (valuechanged != null)
71                     valuechanged(this, null);
72                 ucwave1.height = (int)((double)m_value / (double)m_maxvalue * this.height) + ucwave1.waveheight;
73                 refresh();
74             }
75             get
76             {
77                 return m_value;
78             }
79         }
80 
81         private int m_maxvalue = 100;
82 
83         [description("最大值"), category("自定义")]
84         public int maxvalue
85         {
86             get { return m_maxvalue; }
87             set
88             {
89                 if (value < m_value)
90                     m_maxvalue = m_value;
91                 else
92                     m_maxvalue = value;
93                 refresh();
94             }
95         }
96 
97         public override font font
98         {
99             get
100             {
101                 return base.font;
102             }
103             set
104             {
105                 base.font = value;
106             }
107         }
108 
109         public override color forecolor
110         {
111             get
112             {
113                 return base.forecolor;
114             }
115             set
116             {
117                 base.forecolor = value;
118             }
119         }
120 
121         [description("值颜色"), category("自定义")]
122         public color valuecolor
123         {
124             get { return this.ucwave1.wavecolor; }
125             set
126             {
127                 this.ucwave1.wavecolor = value;
128             }
129         }
130 
131         [description("边框宽度"), category("自定义")]
132         public override int rectwidth
133         {
134             get
135             {
136                 return base.rectwidth;
137             }
138             set
139             {
140                 if (value < 4)
141                     base.rectwidth = 4;
142                 else
143                     base.rectwidth = value;
144             }
145         }
146 
147         public ucprocesswave()
148         {
149             initializecomponent();
150             this.setstyle(controlstyles.allpaintinginwmpaint, true);
151             this.setstyle(controlstyles.doublebuffer, true);
152             this.setstyle(controlstyles.resizeredraw, true);
153             this.setstyle(controlstyles.selectable, true);
154             this.setstyle(controlstyles.supportstransparentbackcolor, true);
155             this.setstyle(controlstyles.userpaint, true);
156             base.isradius = true;
157             base.isshowrect = false;
158             rectwidth = 4;
159             rectcolor = color.white;
160             ucwave1.height = (int)((double)m_value / (double)m_maxvalue * this.height) + ucwave1.waveheight;
161             this.sizechanged += ucprocesswave_sizechanged;
162             this.ucwave1.onpainted += ucwave1_painted;
163             base.conerradius = math.min(this.width, this.height);
164         }
165 
166         void ucwave1_painted(object sender, painteventargs e)
167         {
168             e.graphics.setgdihigh();
169             if (isshowrect)
170             {
171                 if (m_isrectangle)
172                 {
173                     color rectcolor = rectcolor;
174                     pen pen = new pen(rectcolor, (float)rectwidth);
175                     rectangle clientrectangle = new rectangle(0, this.ucwave1.height - this.height, this.width, this.height);
176                     graphicspath graphicspath = new graphicspath();
177                     graphicspath.addarc(clientrectangle.x, clientrectangle.y, 10, 10, 180f, 90f);
178                     graphicspath.addarc(clientrectangle.width - 10 - 1, clientrectangle.y, 10, 10, 270f, 90f);
179                     graphicspath.addarc(clientrectangle.width - 10 - 1, clientrectangle.bottom - 10 - 1, 10, 10, 0f, 90f);
180                     graphicspath.addarc(clientrectangle.x, clientrectangle.bottom - 10 - 1, 10, 10, 90f, 90f);
181                     graphicspath.closefigure();
182                     e.graphics.drawpath(pen, graphicspath);
183                 }
184                 else
185                 {
186                     solidbrush solidbrush = new solidbrush(rectcolor);
187                     e.graphics.drawellipse(new pen(solidbrush, rectwidth), new rectangle(0, this.ucwave1.height - this.height, this.width, this.height));
188                 }
189             }
190 
191             if (!m_isrectangle)
192             {
193                 //这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
194                 solidbrush solidbrush1 = new solidbrush(color.white);
195                 e.graphics.drawellipse(new pen(solidbrush1, 2), new rectangle(-1, this.ucwave1.height - this.height - 1, this.width + 2, this.height + 2));
196             }
197             string strvalue = ((double)m_value / (double)m_maxvalue).tostring("0.%");
198             system.drawing.sizef sizef = e.graphics.measurestring(strvalue, font);
199             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));
200         }
201 
202         void ucprocesswave_sizechanged(object sender, eventargs e)
203         {
204             if (!m_isrectangle)
205             {
206                 base.conerradius = math.min(this.width, this.height);
207                 if (this.width != this.height)
208                 {
209                     this.size = new size(math.min(this.width, this.height), math.min(this.width, this.height));
210                 }
211             }
212         }
213 
214         protected override void onpaint(painteventargs e)
215         {
216             base.onpaint(e);
217             e.graphics.setgdihigh();
218             if (!m_isrectangle)
219             {
220                 //这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
221                 solidbrush solidbrush = new solidbrush(color.white);
222                 e.graphics.drawellipse(new pen(solidbrush, 2), new rectangle(-1, -1, this.width + 2, this.height + 2));
223             }
224             string strvalue = ((double)m_value / (double)m_maxvalue).tostring("0.%");
225             system.drawing.sizef sizef = e.graphics.measurestring(strvalue, font);
226             e.graphics.drawstring(strvalue, font, new solidbrush(forecolor), new pointf((this.width - sizef.width) / 2, (this.height - sizef.height) / 2 + 1));
227         }
228     }
229 }
 1 namespace hzh_controls.controls
2 {
3     partial class ucprocesswave
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             this.ucwave1 = new hzh_controls.controls.ucwave();
32             this.suspendlayout();
33             // 
34             // ucwave1
35             // 
36             this.ucwave1.dock = system.windows.forms.dockstyle.bottom;
37             this.ucwave1.location = new system.drawing.point(0, 140);
38             this.ucwave1.name = "ucwave1";
39             this.ucwave1.size = new system.drawing.size(150, 10);
40             this.ucwave1.tabindex = 0;
41             this.ucwave1.text = "ucwave1";
42             this.ucwave1.wavecolor = system.drawing.color.fromargb(((int)(((byte)(73)))), ((int)(((byte)(119)))), ((int)(((byte)(232)))));
43             this.ucwave1.waveheight = 15;
44             this.ucwave1.wavesleep = 100;
45             this.ucwave1.wavewidth = 100;
46             // 
47             // ucprocesswave
48             // 
49             this.autoscalemode = system.windows.forms.autoscalemode.none;
50             this.backcolor = system.drawing.color.fromargb(((int)(((byte)(197)))), ((int)(((byte)(229)))), ((int)(((byte)(250)))));
51             this.controls.add(this.ucwave1);
52             this.name = "ucprocesswave";
53             this.size = new system.drawing.size(150, 150);
54             this.resumelayout(false);
55 
56         }
57 
58         #endregion
59 
60         private ucwave ucwave1;
61     }
62 }

 

最后的话

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