(五十四)c#Winform自定义控件-仪表盘 - 冰封一夏
source link: https://www.cnblogs.com/bfyx/p/11457234.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
欢迎前来交流探讨: 企鹅群568015492
麻烦博客下方点个【推荐】,谢谢
NuGet
Install-Package HZH_Controls
https://www.cnblogs.com/bfyx/p/11364884.html
用处及效果
依然使用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 }
代码就这么多了,看完整代码
View Code
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧
Recommend
-
78
原标题:北京“扫黄打非”办查封同性直播平台“Peepla”涉男性淫秽表演11月22日,封面新闻记者从全国“扫黄打非”办公室了解到,今年10月,北京市“扫黄打非”办协调相关部门破获“Peepla”直播传播淫秽色情信息案,抓获犯罪嫌疑人17人。
-
18
负载均衡集群先介绍到这里,后续再补充吧
-
57
前言 由于项目需要使用到仪表盘图表,所以就本着一贯的操作流程就来github上面找,结果发现很多图表或者不是我需要的或者扩展性不强,所以就自己动手写了一个扩展性较强的,希望能帮助到有需要的人。(不过本人能力有限,有不足的地方还请见谅) 效果 详细的使用请...
-
52
c#Winform自定义控件-目录-HZHControls 作者:
-
60
http://www.hzhcontrols.com 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 GitHub:
-
46
http://www.hzhcontrols.com 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 GitHub:
-
43
http://www.hzhcontrols.com 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。 GitHub:
-
53
500_请求出错 - 博客园 500 - 系统发生了错误。抱歉,给您带来麻烦了! 麻烦您发邮件至 [email protected] 向我们反馈。 返回网站首页
-
19
0、前言 前面一篇文章写道了仪表盘的特点,实现了一个贴图的仪表盘,属于低配版本的仪表盘。 主要是有任何改动时候就需要重新设计图片,不能适配不同控件大小,即使让它自由拉伸,但仪表盘放大缩小时候显示效果会变差。...
-
5
1. 预览图...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK