(五十四)c#Winform自定义控件-仪表盘
程序员文章站
2022-08-02 09:02:42
前提 入行已经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+画的,不懂的话就百度一下吧
另外主要用到了三角函数,如果不懂,可以向初中的数学老师再问问(你也可以百度一下)
开始
添加一个类ucmeter 继承 usercontrol
首先添加一个需要控制的属性
1 private int splitcount = 10; 2 /// <summary> 3 /// gets or sets the split count. 4 /// </summary> 5 /// <value>the split count.</value> 6 [description("分隔刻度数量,>1"), category("自定义")] 7 public int splitcount 8 { 9 get { return splitcount; } 10 set 11 { 12 if (value < 1) 13 return; 14 splitcount = value; 15 refresh(); 16 } 17 } 18 19 private int meterdegrees = 150; 20 /// <summary> 21 /// gets or sets the meter degrees. 22 /// </summary> 23 /// <value>the meter degrees.</value> 24 [description("表盘跨度角度,0-360"), category("自定义")] 25 public int meterdegrees 26 { 27 get { return meterdegrees; } 28 set 29 { 30 if (value > 360 || value <= 0) 31 return; 32 meterdegrees = value; 33 refresh(); 34 } 35 } 36 37 private decimal minvalue = 0; 38 /// <summary> 39 /// gets or sets the minimum value. 40 /// </summary> 41 /// <value>the minimum value.</value> 42 [description("最小值,<maxvalue"), category("自定义")] 43 public decimal minvalue 44 { 45 get { return minvalue; } 46 set 47 { 48 if (value >= maxvalue) 49 return; 50 minvalue = value; 51 refresh(); 52 } 53 } 54 55 private decimal maxvalue = 100; 56 /// <summary> 57 /// gets or sets the maximum value. 58 /// </summary> 59 /// <value>the maximum value.</value> 60 [description("最大值,>minvalue"), category("自定义")] 61 public decimal maxvalue 62 { 63 get { return maxvalue; } 64 set 65 { 66 if (value <= minvalue) 67 return; 68 maxvalue = value; 69 refresh(); 70 } 71 } 72 /// <summary> 73 /// 获取或设置控件显示的文字的字体。 74 /// </summary> 75 /// <value>the font.</value> 76 /// <permissionset> 77 /// <ipermission class="system.security.permissions.environmentpermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" /> 78 /// <ipermission class="system.security.permissions.fileiopermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" /> 79 /// <ipermission class="system.security.permissions.securitypermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" flags="unmanagedcode, controlevidence" /> 80 /// <ipermission class="system.diagnostics.performancecounterpermission, system, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" /> 81 /// </permissionset> 82 [description("刻度字体"), category("自定义")] 83 public override font font 84 { 85 get 86 { 87 return base.font; 88 } 89 set 90 { 91 base.font = value; 92 refresh(); 93 } 94 } 95 96 private decimal m_value = 0; 97 /// <summary> 98 /// gets or sets the value. 99 /// </summary> 100 /// <value>the value.</value> 101 [description("值,>=minvalue并且<=maxvalue"), category("自定义")] 102 public decimal value 103 { 104 get { return m_value; } 105 set 106 { 107 if (value < minvalue || value > maxvalue) 108 return; 109 m_value = value; 110 refresh(); 111 } 112 } 113 114 private metertextlocation textlocation = metertextlocation.none; 115 /// <summary> 116 /// gets or sets the text location. 117 /// </summary> 118 /// <value>the text location.</value> 119 [description("值和固定文字显示位置"), category("自定义")] 120 public metertextlocation textlocation 121 { 122 get { return textlocation; } 123 set 124 { 125 textlocation = value; 126 refresh(); 127 } 128 } 129 130 private string fixedtext; 131 /// <summary> 132 /// gets or sets the fixed text. 133 /// </summary> 134 /// <value>the fixed text.</value> 135 [description("固定文字"), category("自定义")] 136 public string fixedtext 137 { 138 get { return fixedtext; } 139 set 140 { 141 fixedtext = value; 142 refresh(); 143 } 144 } 145 146 private font textfont = defaultfont; 147 /// <summary> 148 /// gets or sets the text font. 149 /// </summary> 150 /// <value>the text font.</value> 151 [description("值和固定文字字体"), category("自定义")] 152 public font textfont 153 { 154 get { return textfont; } 155 set 156 { 157 textfont = value; 158 refresh(); 159 } 160 } 161 162 private color externalroundcolor = color.fromargb(255, 77, 59); 163 /// <summary> 164 /// gets or sets the color of the external round. 165 /// </summary> 166 /// <value>the color of the external round.</value> 167 [description("外圆颜色"), category("自定义")] 168 public color externalroundcolor 169 { 170 get { return externalroundcolor; } 171 set 172 { 173 externalroundcolor = value; 174 refresh(); 175 } 176 } 177 178 private color insideroundcolor = color.fromargb(255, 77, 59); 179 /// <summary> 180 /// gets or sets the color of the inside round. 181 /// </summary> 182 /// <value>the color of the inside round.</value> 183 [description("内圆颜色"), category("自定义")] 184 public color insideroundcolor 185 { 186 get { return insideroundcolor; } 187 set 188 { 189 insideroundcolor = value; 190 refresh(); 191 } 192 } 193 194 private color boundarylinecolor = color.fromargb(255, 77, 59); 195 /// <summary> 196 /// gets or sets the color of the boundary line. 197 /// </summary> 198 /// <value>the color of the boundary line.</value> 199 [description("边界线颜色"), category("自定义")] 200 public color boundarylinecolor 201 { 202 get { return boundarylinecolor; } 203 set 204 { 205 boundarylinecolor = value; 206 refresh(); 207 } 208 } 209 210 private color scalecolor = color.fromargb(255, 77, 59); 211 /// <summary> 212 /// gets or sets the color of the scale. 213 /// </summary> 214 /// <value>the color of the scale.</value> 215 [description("刻度颜色"), category("自定义")] 216 public color scalecolor 217 { 218 get { return scalecolor; } 219 set 220 { 221 scalecolor = value; 222 refresh(); 223 } 224 } 225 226 private color scalevaluecolor = color.fromargb(255, 77, 59); 227 /// <summary> 228 /// gets or sets the color of the scale value. 229 /// </summary> 230 /// <value>the color of the scale value.</value> 231 [description("刻度值文字颜色"), category("自定义")] 232 public color scalevaluecolor 233 { 234 get { return scalevaluecolor; } 235 set 236 { 237 scalevaluecolor = value; 238 refresh(); 239 } 240 } 241 242 private color pointercolor = color.fromargb(255, 77, 59); 243 /// <summary> 244 /// gets or sets the color of the pointer. 245 /// </summary> 246 /// <value>the color of the pointer.</value> 247 [description("指针颜色"), category("自定义")] 248 public color pointercolor 249 { 250 get { return pointercolor; } 251 set 252 { 253 pointercolor = value; 254 refresh(); 255 } 256 } 257 258 private color textcolor = color.fromargb(255, 77, 59); 259 /// <summary> 260 /// gets or sets the color of the text. 261 /// </summary> 262 /// <value>the color of the text.</value> 263 [description("值和固定文字颜色"), category("自定义")] 264 public color textcolor 265 { 266 get { return textcolor; } 267 set 268 { 269 textcolor = value; 270 refresh(); 271 } 272 } 273 274 rectangle m_rectworking;
重绘
1 protected override void onpaint(painteventargs e) 2 { 3 base.onpaint(e); 4 var g = e.graphics; 5 g.setgdihigh(); 6 7 //外圆 8 float fltstartangle = -90 - (meterdegrees) / 2 + 360; 9 var r1 = new rectangle(m_rectworking.location, new size(m_rectworking.width, m_rectworking.width)); 10 g.drawarc(new pen(new solidbrush(externalroundcolor), 1), r1, fltstartangle, meterdegrees); 11 //内圆 12 var r2 = new rectangle(m_rectworking.left + (m_rectworking.width - m_rectworking.width / 4) / 2, m_rectworking.top + (m_rectworking.width - m_rectworking.width / 4) / 2, m_rectworking.width / 4, m_rectworking.width / 4); 13 g.drawarc(new pen(new solidbrush(insideroundcolor), 1), r2, fltstartangle, meterdegrees); 14 15 //边界线 16 if (meterdegrees != 360) 17 { 18 float fltangle = fltstartangle - 180; 19 20 float inty = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - m_rectworking.width / 8) * math.sin(math.pi * (fltangle / 180.00f)))); 21 float intx = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - m_rectworking.width / 8) * math.cos(math.pi * (fltangle / 180.00f))))); 22 23 float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - (m_rectworking.width / 8 * math.sin(math.pi * (fltangle / 180.00f)))); 24 float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - (m_rectworking.width / 8 * math.cos(math.pi * (fltangle / 180.00f))))); 25 26 g.drawline(new pen(new solidbrush(boundarylinecolor), 1), new pointf(intx, inty), new pointf(fltx1, flty1)); 27 g.drawline(new pen(new solidbrush(boundarylinecolor), 1), new pointf(m_rectworking.right - (fltx1 - m_rectworking.left), flty1), new pointf(m_rectworking.right - (intx - m_rectworking.left), inty)); 28 } 29 30 //分割线 31 int _splitcount = splitcount * 2; 32 float fltsplitvalue = (float)meterdegrees / (float)_splitcount; 33 for (int i = 0; i <= _splitcount; i++) 34 { 35 float fltangle = (fltstartangle + fltsplitvalue * i - 180) % 360; 36 float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.sin(math.pi * (fltangle / 180.00f)))); 37 float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.cos(math.pi * (fltangle / 180.00f))))); 38 float flty2 = 0; 39 float fltx2 = 0; 40 if (i % 2 == 0) 41 { 42 flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.sin(math.pi * (fltangle / 180.00f)))); 43 fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.cos(math.pi * (fltangle / 180.00f))))); 44 if (!(meterdegrees == 360 && i == _splitcount)) 45 { 46 decimal decvalue = minvalue + (maxvalue - minvalue) / _splitcount * i; 47 var txtsize = g.measurestring(decvalue.tostring("0.##"), this.font); 48 float fltfy1 = (float)(m_rectworking.top - txtsize.height / 2 + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 20) * math.sin(math.pi * (fltangle / 180.00f)))); 49 float fltfx1 = (float)(m_rectworking.left - txtsize.width / 2 + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 20) * math.cos(math.pi * (fltangle / 180.00f))))); 50 g.drawstring(decvalue.tostring("0.##"), font, new solidbrush(scalevaluecolor), fltfx1, fltfy1); 51 } 52 } 53 else 54 { 55 flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.sin(math.pi * (fltangle / 180.00f)))); 56 fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.cos(math.pi * (fltangle / 180.00f))))); 57 } 58 g.drawline(new pen(new solidbrush(scalecolor), i % 2 == 0 ? 2 : 1), new pointf(fltx1, flty1), new pointf(fltx2, flty2)); 59 } 60 61 //值文字和固定文字 62 if (textlocation != metertextlocation.none) 63 { 64 string str = m_value.tostring("0.##"); 65 var txtsize = g.measurestring(str, textfont); 66 float flty = m_rectworking.top + m_rectworking.width / 4 - txtsize.height / 2; 67 float fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2; 68 g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty)); 69 70 if (!string.isnullorempty(fixedtext)) 71 { 72 str = fixedtext; 73 txtsize = g.measurestring(str, textfont); 74 flty = m_rectworking.top + m_rectworking.width / 4 + txtsize.height / 2; 75 fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2; 76 g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty)); 77 } 78 } 79 80 //画指针 81 g.fillellipse(new solidbrush(color.fromargb(100, pointercolor.r, pointercolor.g, pointercolor.b)), new rectangle(m_rectworking.left + m_rectworking.width / 2 - 10, m_rectworking.top + m_rectworking.width / 2 - 10, 20, 20)); 82 g.fillellipse(brushes.red, new rectangle(m_rectworking.left + m_rectworking.width / 2 - 5, m_rectworking.top + m_rectworking.width / 2 - 5, 10, 10)); 83 float fltvalueangle = (fltstartangle + ((float)(m_value - minvalue) / (float)(maxvalue - minvalue)) * (float)meterdegrees - 180) % 360; 84 float intvaluey1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.sin(math.pi * (fltvalueangle / 180.00f)))); 85 float intvaluex1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.cos(math.pi * (fltvalueangle / 180.00f))))); 86 g.drawline(new pen(new solidbrush(pointercolor), 3), intvaluex1, intvaluey1, m_rectworking.left + m_rectworking.width / 2, m_rectworking.top + m_rectworking.width / 2); 87 }
还有一个显示文字位置的枚举
1 /// <summary> 2 /// enum metertextlocation 3 /// </summary> 4 public enum metertextlocation 5 { 6 /// <summary> 7 /// the none 8 /// </summary> 9 none, 10 /// <summary> 11 /// the top 12 /// </summary> 13 top, 14 /// <summary> 15 /// the bottom 16 /// </summary> 17 bottom 18 }
代码就这么多了,看完整代码
1 // *********************************************************************** 2 // assembly : hzh_controls 3 // created : 2019-09-03 4 // 5 // *********************************************************************** 6 // <copyright file="ucmeter.cs"> 7 // copyright by huang zhenghui(黄正辉) all, qq group:568015492 qq:623128629 email:623128629@qq.com 8 // </copyright> 9 // 10 // blog: https://www.cnblogs.com/bfyx 11 // github:https://github.com/kwwwvagaa/netwinformcontrol 12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git 13 // 14 // if you use this code, please keep this note. 15 // *********************************************************************** 16 using system; 17 using system.collections.generic; 18 using system.linq; 19 using system.text; 20 using system.windows.forms; 21 using system.drawing; 22 using system.drawing.drawing2d; 23 using system.componentmodel; 24 25 namespace hzh_controls.controls 26 { 27 /// <summary> 28 /// class ucmeter. 29 /// implements the <see cref="system.windows.forms.usercontrol" /> 30 /// </summary> 31 /// <seealso cref="system.windows.forms.usercontrol" /> 32 public class ucmeter : usercontrol 33 { 34 private int splitcount = 10; 35 /// <summary> 36 /// gets or sets the split count. 37 /// </summary> 38 /// <value>the split count.</value> 39 [description("分隔刻度数量,>1"), category("自定义")] 40 public int splitcount 41 { 42 get { return splitcount; } 43 set 44 { 45 if (value < 1) 46 return; 47 splitcount = value; 48 refresh(); 49 } 50 } 51 52 private int meterdegrees = 150; 53 /// <summary> 54 /// gets or sets the meter degrees. 55 /// </summary> 56 /// <value>the meter degrees.</value> 57 [description("表盘跨度角度,0-360"), category("自定义")] 58 public int meterdegrees 59 { 60 get { return meterdegrees; } 61 set 62 { 63 if (value > 360 || value <= 0) 64 return; 65 meterdegrees = value; 66 refresh(); 67 } 68 } 69 70 private decimal minvalue = 0; 71 /// <summary> 72 /// gets or sets the minimum value. 73 /// </summary> 74 /// <value>the minimum value.</value> 75 [description("最小值,<maxvalue"), category("自定义")] 76 public decimal minvalue 77 { 78 get { return minvalue; } 79 set 80 { 81 if (value >= maxvalue) 82 return; 83 minvalue = value; 84 refresh(); 85 } 86 } 87 88 private decimal maxvalue = 100; 89 /// <summary> 90 /// gets or sets the maximum value. 91 /// </summary> 92 /// <value>the maximum value.</value> 93 [description("最大值,>minvalue"), category("自定义")] 94 public decimal maxvalue 95 { 96 get { return maxvalue; } 97 set 98 { 99 if (value <= minvalue) 100 return; 101 maxvalue = value; 102 refresh(); 103 } 104 } 105 /// <summary> 106 /// 获取或设置控件显示的文字的字体。 107 /// </summary> 108 /// <value>the font.</value> 109 /// <permissionset> 110 /// <ipermission class="system.security.permissions.environmentpermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" /> 111 /// <ipermission class="system.security.permissions.fileiopermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" /> 112 /// <ipermission class="system.security.permissions.securitypermission, mscorlib, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" flags="unmanagedcode, controlevidence" /> 113 /// <ipermission class="system.diagnostics.performancecounterpermission, system, version=2.0.3600.0, culture=neutral, publickeytoken=b77a5c561934e089" version="1" unrestricted="true" /> 114 /// </permissionset> 115 [description("刻度字体"), category("自定义")] 116 public override font font 117 { 118 get 119 { 120 return base.font; 121 } 122 set 123 { 124 base.font = value; 125 refresh(); 126 } 127 } 128 129 private decimal m_value = 0; 130 /// <summary> 131 /// gets or sets the value. 132 /// </summary> 133 /// <value>the value.</value> 134 [description("值,>=minvalue并且<=maxvalue"), category("自定义")] 135 public decimal value 136 { 137 get { return m_value; } 138 set 139 { 140 if (value < minvalue || value > maxvalue) 141 return; 142 m_value = value; 143 refresh(); 144 } 145 } 146 147 private metertextlocation textlocation = metertextlocation.none; 148 /// <summary> 149 /// gets or sets the text location. 150 /// </summary> 151 /// <value>the text location.</value> 152 [description("值和固定文字显示位置"), category("自定义")] 153 public metertextlocation textlocation 154 { 155 get { return textlocation; } 156 set 157 { 158 textlocation = value; 159 refresh(); 160 } 161 } 162 163 private string fixedtext; 164 /// <summary> 165 /// gets or sets the fixed text. 166 /// </summary> 167 /// <value>the fixed text.</value> 168 [description("固定文字"), category("自定义")] 169 public string fixedtext 170 { 171 get { return fixedtext; } 172 set 173 { 174 fixedtext = value; 175 refresh(); 176 } 177 } 178 179 private font textfont = defaultfont; 180 /// <summary> 181 /// gets or sets the text font. 182 /// </summary> 183 /// <value>the text font.</value> 184 [description("值和固定文字字体"), category("自定义")] 185 public font textfont 186 { 187 get { return textfont; } 188 set 189 { 190 textfont = value; 191 refresh(); 192 } 193 } 194 195 private color externalroundcolor = color.fromargb(255, 77, 59); 196 /// <summary> 197 /// gets or sets the color of the external round. 198 /// </summary> 199 /// <value>the color of the external round.</value> 200 [description("外圆颜色"), category("自定义")] 201 public color externalroundcolor 202 { 203 get { return externalroundcolor; } 204 set 205 { 206 externalroundcolor = value; 207 refresh(); 208 } 209 } 210 211 private color insideroundcolor = color.fromargb(255, 77, 59); 212 /// <summary> 213 /// gets or sets the color of the inside round. 214 /// </summary> 215 /// <value>the color of the inside round.</value> 216 [description("内圆颜色"), category("自定义")] 217 public color insideroundcolor 218 { 219 get { return insideroundcolor; } 220 set 221 { 222 insideroundcolor = value; 223 refresh(); 224 } 225 } 226 227 private color boundarylinecolor = color.fromargb(255, 77, 59); 228 /// <summary> 229 /// gets or sets the color of the boundary line. 230 /// </summary> 231 /// <value>the color of the boundary line.</value> 232 [description("边界线颜色"), category("自定义")] 233 public color boundarylinecolor 234 { 235 get { return boundarylinecolor; } 236 set 237 { 238 boundarylinecolor = value; 239 refresh(); 240 } 241 } 242 243 private color scalecolor = color.fromargb(255, 77, 59); 244 /// <summary> 245 /// gets or sets the color of the scale. 246 /// </summary> 247 /// <value>the color of the scale.</value> 248 [description("刻度颜色"), category("自定义")] 249 public color scalecolor 250 { 251 get { return scalecolor; } 252 set 253 { 254 scalecolor = value; 255 refresh(); 256 } 257 } 258 259 private color scalevaluecolor = color.fromargb(255, 77, 59); 260 /// <summary> 261 /// gets or sets the color of the scale value. 262 /// </summary> 263 /// <value>the color of the scale value.</value> 264 [description("刻度值文字颜色"), category("自定义")] 265 public color scalevaluecolor 266 { 267 get { return scalevaluecolor; } 268 set 269 { 270 scalevaluecolor = value; 271 refresh(); 272 } 273 } 274 275 private color pointercolor = color.fromargb(255, 77, 59); 276 /// <summary> 277 /// gets or sets the color of the pointer. 278 /// </summary> 279 /// <value>the color of the pointer.</value> 280 [description("指针颜色"), category("自定义")] 281 public color pointercolor 282 { 283 get { return pointercolor; } 284 set 285 { 286 pointercolor = value; 287 refresh(); 288 } 289 } 290 291 private color textcolor = color.fromargb(255, 77, 59); 292 /// <summary> 293 /// gets or sets the color of the text. 294 /// </summary> 295 /// <value>the color of the text.</value> 296 [description("值和固定文字颜色"), category("自定义")] 297 public color textcolor 298 { 299 get { return textcolor; } 300 set 301 { 302 textcolor = value; 303 refresh(); 304 } 305 } 306 307 rectangle m_rectworking; 308 public ucmeter() 309 { 310 this.setstyle(controlstyles.allpaintinginwmpaint, true); 311 this.setstyle(controlstyles.doublebuffer, true); 312 this.setstyle(controlstyles.resizeredraw, true); 313 this.setstyle(controlstyles.selectable, true); 314 this.setstyle(controlstyles.supportstransparentbackcolor, true); 315 this.setstyle(controlstyles.userpaint, true); 316 this.sizechanged += ucmeter1_sizechanged; 317 this.autoscalemode = system.windows.forms.autoscalemode.none; 318 this.size = new size(350, 200); 319 } 320 321 void ucmeter1_sizechanged(object sender, eventargs e) 322 { 323 m_rectworking = new rectangle(10, 10, this.width - 20, this.height - 20); 324 } 325 326 327 protected override void onpaint(painteventargs e) 328 { 329 base.onpaint(e); 330 var g = e.graphics; 331 g.setgdihigh(); 332 333 //外圆 334 float fltstartangle = -90 - (meterdegrees) / 2 + 360; 335 var r1 = new rectangle(m_rectworking.location, new size(m_rectworking.width, m_rectworking.width)); 336 g.drawarc(new pen(new solidbrush(externalroundcolor), 1), r1, fltstartangle, meterdegrees); 337 //内圆 338 var r2 = new rectangle(m_rectworking.left + (m_rectworking.width - m_rectworking.width / 4) / 2, m_rectworking.top + (m_rectworking.width - m_rectworking.width / 4) / 2, m_rectworking.width / 4, m_rectworking.width / 4); 339 g.drawarc(new pen(new solidbrush(insideroundcolor), 1), r2, fltstartangle, meterdegrees); 340 341 //边界线 342 if (meterdegrees != 360) 343 { 344 float fltangle = fltstartangle - 180; 345 346 float inty = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - m_rectworking.width / 8) * math.sin(math.pi * (fltangle / 180.00f)))); 347 float intx = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - m_rectworking.width / 8) * math.cos(math.pi * (fltangle / 180.00f))))); 348 349 float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - (m_rectworking.width / 8 * math.sin(math.pi * (fltangle / 180.00f)))); 350 float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - (m_rectworking.width / 8 * math.cos(math.pi * (fltangle / 180.00f))))); 351 352 g.drawline(new pen(new solidbrush(boundarylinecolor), 1), new pointf(intx, inty), new pointf(fltx1, flty1)); 353 g.drawline(new pen(new solidbrush(boundarylinecolor), 1), new pointf(m_rectworking.right - (fltx1 - m_rectworking.left), flty1), new pointf(m_rectworking.right - (intx - m_rectworking.left), inty)); 354 } 355 356 //分割线 357 int _splitcount = splitcount * 2; 358 float fltsplitvalue = (float)meterdegrees / (float)_splitcount; 359 for (int i = 0; i <= _splitcount; i++) 360 { 361 float fltangle = (fltstartangle + fltsplitvalue * i - 180) % 360; 362 float flty1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.sin(math.pi * (fltangle / 180.00f)))); 363 float fltx1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2) * math.cos(math.pi * (fltangle / 180.00f))))); 364 float flty2 = 0; 365 float fltx2 = 0; 366 if (i % 2 == 0) 367 { 368 flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.sin(math.pi * (fltangle / 180.00f)))); 369 fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 10) * math.cos(math.pi * (fltangle / 180.00f))))); 370 if (!(meterdegrees == 360 && i == _splitcount)) 371 { 372 decimal decvalue = minvalue + (maxvalue - minvalue) / _splitcount * i; 373 var txtsize = g.measurestring(decvalue.tostring("0.##"), this.font); 374 float fltfy1 = (float)(m_rectworking.top - txtsize.height / 2 + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 20) * math.sin(math.pi * (fltangle / 180.00f)))); 375 float fltfx1 = (float)(m_rectworking.left - txtsize.width / 2 + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 20) * math.cos(math.pi * (fltangle / 180.00f))))); 376 g.drawstring(decvalue.tostring("0.##"), font, new solidbrush(scalevaluecolor), fltfx1, fltfy1); 377 } 378 } 379 else 380 { 381 flty2 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.sin(math.pi * (fltangle / 180.00f)))); 382 fltx2 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 5) * math.cos(math.pi * (fltangle / 180.00f))))); 383 } 384 g.drawline(new pen(new solidbrush(scalecolor), i % 2 == 0 ? 2 : 1), new pointf(fltx1, flty1), new pointf(fltx2, flty2)); 385 } 386 387 //值文字和固定文字 388 if (textlocation != metertextlocation.none) 389 { 390 string str = m_value.tostring("0.##"); 391 var txtsize = g.measurestring(str, textfont); 392 float flty = m_rectworking.top + m_rectworking.width / 4 - txtsize.height / 2; 393 float fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2; 394 g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty)); 395 396 if (!string.isnullorempty(fixedtext)) 397 { 398 str = fixedtext; 399 txtsize = g.measurestring(str, textfont); 400 flty = m_rectworking.top + m_rectworking.width / 4 + txtsize.height / 2; 401 fltx = m_rectworking.left + m_rectworking.width / 2 - txtsize.width / 2; 402 g.drawstring(str, textfont, new solidbrush(textcolor), new pointf(fltx, flty)); 403 } 404 } 405 406 //画指针 407 g.fillellipse(new solidbrush(color.fromargb(100, pointercolor.r, pointercolor.g, pointercolor.b)), new rectangle(m_rectworking.left + m_rectworking.width / 2 - 10, m_rectworking.top + m_rectworking.width / 2 - 10, 20, 20)); 408 g.fillellipse(brushes.red, new rectangle(m_rectworking.left + m_rectworking.width / 2 - 5, m_rectworking.top + m_rectworking.width / 2 - 5, 10, 10)); 409 float fltvalueangle = (fltstartangle + ((float)(m_value - minvalue) / (float)(maxvalue - minvalue)) * (float)meterdegrees - 180) % 360; 410 float intvaluey1 = (float)(m_rectworking.top + m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.sin(math.pi * (fltvalueangle / 180.00f)))); 411 float intvaluex1 = (float)(m_rectworking.left + (m_rectworking.width / 2 - ((m_rectworking.width / 2 - 30) * math.cos(math.pi * (fltvalueangle / 180.00f))))); 412 g.drawline(new pen(new solidbrush(pointercolor), 3), intvaluex1, intvaluey1, m_rectworking.left + m_rectworking.width / 2, m_rectworking.top + m_rectworking.width / 2); 413 } 414 } 415 416 /// <summary> 417 /// enum metertextlocation 418 /// </summary> 419 public enum metertextlocation 420 { 421 /// <summary> 422 /// the none 423 /// </summary> 424 none, 425 /// <summary> 426 /// the top 427 /// </summary> 428 top, 429 /// <summary> 430 /// the bottom 431 /// </summary> 432 bottom 433 } 434 }
最后的话
如果你喜欢的话,请到 点个星星吧
上一篇: WinForm任务栏最小化