(四十六)c#Winform自定义控件-水波进度条
程序员文章站
2022-04-10 23:31:07
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:https://gitee.com/kwwwvagaa/net_winform_custom_contr ......
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
github:https://github.com/kwwwvagaa/netwinformcontrol
码云:
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492
麻烦博客下方点个【推荐】,谢谢
nuget
install-package hzh_controls
目录
用处及效果
准备工作
这个用到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 }
不知道你们有没有注意这句话
//这里曲线救国,因为设置了控件区域导致的毛边,通过画一个没有毛边的圆遮挡
因为设置原价导致了区域毛边,所有画个没有毛边的边框覆盖之
完整代码
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 }
最后的话
如果你喜欢的话,请到 点个星星吧