(六十四)c#Winform自定义控件-温度计(工业)
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
麻烦博客下方点个【推荐】,谢谢
NuGet
Install-Package HZH_Controls
目录
https://www.cnblogs.com/bfyx/p/11364884.html
用处及效果
准备工作
依然用GID+画的,不懂请自行百度
开始
添加一个类UCThermometer,继承UserControl
添加一个枚举,来决定显示的温度单位
1 public enum TemperatureUnit 2 { 3 /// <summary> 4 /// 不显示 5 /// </summary> 6 None, 7 /// <summary> 8 /// 摄氏度 9 /// </summary> 10 C, 11 /// <summary> 12 /// 华氏度 13 /// </summary> 14 F, 15 /// <summary> 16 /// 开氏度 17 /// </summary> 18 K, 19 /// <summary> 20 /// 兰氏度 21 /// </summary> 22 R, 23 /// <summary> 24 /// 列氏度 25 /// </summary> 26 Re 27 }
添加一些属性
1 /// <summary> 2 /// The glass tube color 3 /// </summary> 4 private Color glassTubeColor = Color.FromArgb(211, 211, 211); 5 6 /// <summary> 7 /// Gets or sets the color of the glass tube. 8 /// </summary> 9 /// <value>The color of the glass tube.</value> 10 [Description("玻璃管颜色"), Category("自定义")] 11 public Color GlassTubeColor 12 { 13 get { return glassTubeColor; } 14 set 15 { 16 glassTubeColor = value; 17 Refresh(); 18 } 19 } 20 21 /// <summary> 22 /// The mercury color 23 /// </summary> 24 private Color mercuryColor = Color.FromArgb(255, 77, 59); 25 26 /// <summary> 27 /// Gets or sets the color of the mercury. 28 /// </summary> 29 /// <value>The color of the mercury.</value> 30 [Description("水印颜色"), Category("自定义")] 31 public Color MercuryColor 32 { 33 get { return mercuryColor; } 34 set 35 { 36 mercuryColor = value; 37 Refresh(); 38 } 39 } 40 41 /// <summary> 42 /// The minimum value 43 /// </summary> 44 private decimal minValue = 0; 45 /// <summary> 46 /// 左侧刻度最小值 47 /// </summary> 48 /// <value>The minimum value.</value> 49 [Description("左侧刻度最小值"), Category("自定义")] 50 public decimal MinValue 51 { 52 get { return minValue; } 53 set 54 { 55 minValue = value; 56 Refresh(); 57 } 58 } 59 60 /// <summary> 61 /// The maximum value 62 /// </summary> 63 private decimal maxValue = 100; 64 /// <summary> 65 /// 左侧刻度最大值 66 /// </summary> 67 /// <value>The maximum value.</value> 68 [Description("左侧刻度最大值"), Category("自定义")] 69 public decimal MaxValue 70 { 71 get { return maxValue; } 72 set 73 { 74 maxValue = value; 75 Refresh(); 76 } 77 } 78 79 /// <summary> 80 /// The m value 81 /// </summary> 82 private decimal m_value = 10; 83 /// <summary> 84 /// 左侧刻度值 85 /// </summary> 86 /// <value>The value.</value> 87 [Description("左侧刻度值"), Category("自定义")] 88 public decimal Value 89 { 90 get { return m_value; } 91 set 92 { 93 m_value = value; 94 Refresh(); 95 } 96 } 97 98 /// <summary> 99 /// The split count 100 /// </summary> 101 private int splitCount = 0; 102 /// <summary> 103 /// 刻度分隔份数 104 /// </summary> 105 /// <value>The split count.</value> 106 [Description("刻度分隔份数"), Category("自定义")] 107 public int SplitCount 108 { 109 get { return splitCount; } 110 set 111 { 112 if (value <= 0) 113 return; 114 splitCount = value; 115 Refresh(); 116 } 117 } 118 119 /// <summary> 120 /// 获取或设置控件显示的文字的字体。 121 /// </summary> 122 /// <value>The font.</value> 123 /// <PermissionSet> 124 /// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 125 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 126 /// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" /> 127 /// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 128 /// </PermissionSet> 129 [Description("获取或设置控件显示的文字的字体"), Category("自定义")] 130 public override Font Font 131 { 132 get 133 { 134 return base.Font; 135 } 136 set 137 { 138 base.Font = value; 139 Refresh(); 140 } 141 } 142 143 /// <summary> 144 /// 获取或设置控件的前景色。 145 /// </summary> 146 /// <value>The color of the fore.</value> 147 /// <PermissionSet> 148 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 149 /// </PermissionSet> 150 [Description("获取或设置控件的文字及刻度颜色"), Category("自定义")] 151 public override System.Drawing.Color ForeColor 152 { 153 get 154 { 155 return base.ForeColor; 156 } 157 set 158 { 159 base.ForeColor = value; 160 Refresh(); 161 } 162 } 163 164 /// <summary> 165 /// The left temperature unit 166 /// </summary> 167 private TemperatureUnit leftTemperatureUnit = TemperatureUnit.C; 168 /// <summary> 169 /// 左侧刻度单位,不可为none 170 /// </summary> 171 /// <value>The left temperature unit.</value> 172 [Description("左侧刻度单位,不可为none"), Category("自定义")] 173 public TemperatureUnit LeftTemperatureUnit 174 { 175 get { return leftTemperatureUnit; } 176 set 177 { 178 if (value == TemperatureUnit.None) 179 return; 180 leftTemperatureUnit = value; 181 Refresh(); 182 } 183 } 184 185 /// <summary> 186 /// The right temperature unit 187 /// </summary> 188 private TemperatureUnit rightTemperatureUnit = TemperatureUnit.C; 189 /// <summary> 190 /// 右侧刻度单位,当为none时,不显示 191 /// </summary> 192 /// <value>The right temperature unit.</value> 193 [Description("右侧刻度单位,当为none时,不显示"), Category("自定义")] 194 public TemperatureUnit RightTemperatureUnit 195 { 196 get { return rightTemperatureUnit; } 197 set 198 { 199 rightTemperatureUnit = value; 200 Refresh(); 201 } 202 } 203 204 /// <summary> 205 /// The m rect working 206 /// </summary> 207 Rectangle m_rectWorking; 208 /// <summary> 209 /// The m rect left 210 /// </summary> 211 Rectangle m_rectLeft; 212 /// <summary> 213 /// The m rect right 214 /// </summary> 215 Rectangle m_rectRight;
改变大小时,设定画图区域
1 void UCThermometer_SizeChanged(object sender, EventArgs e) 2 { 3 m_rectWorking = new Rectangle(this.Width / 2 - this.Width / 8, this.Width / 4, this.Width / 4, this.Height - this.Width / 2); 4 m_rectLeft = new Rectangle(0, m_rectWorking.Top + m_rectWorking.Width / 2, (this.Width - this.Width / 4) / 2 - 2, m_rectWorking.Height - m_rectWorking.Width * 2); 5 m_rectRight = new Rectangle(this.Width - (this.Width - this.Width / 4) / 2 + 2, m_rectWorking.Top + m_rectWorking.Width / 2, (this.Width - this.Width / 4) / 2 - 2, m_rectWorking.Height - m_rectWorking.Width * 2); 6 }
重绘
1 protected override void OnPaint(PaintEventArgs e) 2 { 3 base.OnPaint(e); 4 var g = e.Graphics; 5 g.SetGDIHigh(); 6 7 //玻璃管管 8 GraphicsPath path = new GraphicsPath(); 9 path.AddLine(m_rectWorking.Left, m_rectWorking.Bottom, m_rectWorking.Left, m_rectWorking.Top + m_rectWorking.Width / 2); 10 path.AddArc(new Rectangle(m_rectWorking.Left, m_rectWorking.Top, m_rectWorking.Width, m_rectWorking.Width), 180, 180); 11 path.AddLine(m_rectWorking.Right, m_rectWorking.Top + m_rectWorking.Width / 2, m_rectWorking.Right, m_rectWorking.Bottom); 12 path.CloseAllFigures(); 13 g.FillPath(new SolidBrush(glassTubeColor), path); 14 15 //底部 16 var rectDi = new Rectangle(this.Width / 2 - m_rectWorking.Width, m_rectWorking.Bottom - m_rectWorking.Width - 2, m_rectWorking.Width * 2, m_rectWorking.Width * 2); 17 g.FillEllipse(new SolidBrush(glassTubeColor), rectDi); 18 g.FillEllipse(new SolidBrush(mercuryColor), new Rectangle(rectDi.Left + 4, rectDi.Top + 4, rectDi.Width - 8, rectDi.Height - 8)); 19 20 //刻度 21 decimal decSplit = (maxValue - minValue) / splitCount; 22 decimal decSplitHeight = m_rectLeft.Height / splitCount; 23 for (int i = 0; i <= splitCount; i++) 24 { 25 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Left + 2, (float)(m_rectLeft.Bottom - decSplitHeight * i)), new PointF(m_rectLeft.Right, (float)(m_rectLeft.Bottom - decSplitHeight * i))); 26 27 var valueLeft = (minValue + decSplit * i).ToString("0.##"); 28 var sizeLeft = g.MeasureString(valueLeft, Font); 29 g.DrawString(valueLeft, Font, new SolidBrush(ForeColor), new PointF(m_rectLeft.Left, m_rectLeft.Bottom - (float)decSplitHeight * i - sizeLeft.Height - 1)); 30 31 if (rightTemperatureUnit != TemperatureUnit.None) 32 { 33 g.DrawLine(new Pen(new SolidBrush(Color.Black), 1), new PointF(m_rectRight.Left + 2, (float)(m_rectRight.Bottom - decSplitHeight * i)), new PointF(m_rectRight.Right, (float)(m_rectRight.Bottom - decSplitHeight * i))); 34 var valueRight = GetRightValue(minValue + decSplit * i).ToString("0.##"); 35 var sizeRight = g.MeasureString(valueRight, Font); 36 g.DrawString(valueRight, Font, new SolidBrush(ForeColor), new PointF(m_rectRight.Right - sizeRight.Width - 1, m_rectRight.Bottom - (float)decSplitHeight * i - sizeRight.Height - 1)); 37 } 38 if (i != splitCount) 39 { 40 if (decSplitHeight > 40) 41 { 42 var decSp1 = decSplitHeight / 10; 43 for (int j = 1; j < 10; j++) 44 { 45 if (j == 5) 46 { 47 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Right - 10, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectLeft.Right, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 48 if (rightTemperatureUnit != TemperatureUnit.None) 49 { 50 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectRight.Left + 10, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectRight.Left, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 51 } 52 } 53 else 54 { 55 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Right - 5, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectLeft.Right, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 56 if (rightTemperatureUnit != TemperatureUnit.None) 57 { 58 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectRight.Left + 5, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectRight.Left, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 59 } 60 } 61 } 62 } 63 else if (decSplitHeight > 10) 64 { 65 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Right - 5, (m_rectLeft.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2)), new PointF(m_rectLeft.Right, (m_rectLeft.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2))); 66 if (rightTemperatureUnit != TemperatureUnit.None) 67 { 68 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectRight.Left + 5, (m_rectRight.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2)), new PointF(m_rectRight.Left, (m_rectRight.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2))); 69 } 70 } 71 } 72 } 73 //单位 74 string strLeftUnit = GetUnitChar(leftTemperatureUnit); 75 g.DrawString(strLeftUnit, Font, new SolidBrush(ForeColor), new PointF(m_rectLeft.Left + 2, 2)); 76 if (rightTemperatureUnit != TemperatureUnit.None) 77 { 78 string strRightUnit = GetUnitChar(rightTemperatureUnit); 79 var rightSize = g.MeasureString(strRightUnit, Font); 80 g.DrawString(strRightUnit, Font, new SolidBrush(ForeColor), new PointF(m_rectRight.Right - 2 - rightSize.Width, 2)); 81 } 82 //值 83 float fltHeightValue = (float)(Value / (maxValue - minValue) * m_rectLeft.Height); 84 RectangleF rectValue = new RectangleF(m_rectWorking.Left + 4, m_rectLeft.Top + (m_rectLeft.Height - fltHeightValue), m_rectWorking.Width - 8, fltHeightValue + (m_rectWorking.Height - m_rectWorking.Width / 2 - m_rectLeft.Height)); 85 g.FillRectangle(new SolidBrush(mercuryColor), rectValue); 86 87 88 var sizeValue = g.MeasureString(m_value.ToString("0.##"), Font); 89 g.DrawString(m_value.ToString("0.##"), Font, new SolidBrush(Color.White), new PointF(rectDi.Left + (rectDi.Width - sizeValue.Width) / 2, rectDi.Top + (rectDi.Height - sizeValue.Height) / 2 + 1)); 90 }
辅助函数
1 private string GetUnitChar(TemperatureUnit unit) 2 { 3 string strUnit = "℃"; 4 switch (unit) 5 { 6 case TemperatureUnit.C: 7 strUnit = "℃"; 8 break; 9 case TemperatureUnit.F: 10 strUnit = "℉"; 11 break; 12 case TemperatureUnit.K: 13 strUnit = "K"; 14 break; 15 case TemperatureUnit.R: 16 strUnit = "°R"; 17 break; 18 case TemperatureUnit.Re: 19 strUnit = "°Re"; 20 break; 21 } 22 return strUnit; 23 } 24 25 private decimal GetRightValue(decimal decValue) 26 { 27 //先将左侧的换算为摄氏度 28 var dec = decValue; 29 switch (leftTemperatureUnit) 30 { 31 case TemperatureUnit.F: 32 dec = (decValue - 32) / (9M / 5M); 33 break; 34 case TemperatureUnit.K: 35 dec = decValue - 273; 36 break; 37 case TemperatureUnit.R: 38 dec = decValue / (5M / 9M) - 273.15M; 39 break; 40 case TemperatureUnit.Re: 41 dec = decValue / 1.25M; 42 break; 43 default: 44 break; 45 } 46 47 switch (rightTemperatureUnit) 48 { 49 case TemperatureUnit.C: 50 return dec; 51 case TemperatureUnit.F: 52 return 9M / 5M * dec + 32; 53 case TemperatureUnit.K: 54 return dec + 273; 55 case TemperatureUnit.R: 56 return (dec + 273.15M) * (5M / 9M); 57 case TemperatureUnit.Re: 58 return dec * 1.25M; 59 } 60 return decValue; 61 }
完整代码
1 // *********************************************************************** 2 // Assembly : HZH_Controls 3 // Created : 2019-09-10 4 // 5 // *********************************************************************** 6 // <copyright file="UCThermometer.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 UCThermometer. 29 /// Implements the <see cref="System.Windows.Forms.UserControl" /> 30 /// </summary> 31 /// <seealso cref="System.Windows.Forms.UserControl" /> 32 public class UCThermometer : UserControl 33 { 34 /// <summary> 35 /// The glass tube color 36 /// </summary> 37 private Color glassTubeColor = Color.FromArgb(211, 211, 211); 38 39 /// <summary> 40 /// Gets or sets the color of the glass tube. 41 /// </summary> 42 /// <value>The color of the glass tube.</value> 43 [Description("玻璃管颜色"), Category("自定义")] 44 public Color GlassTubeColor 45 { 46 get { return glassTubeColor; } 47 set 48 { 49 glassTubeColor = value; 50 Refresh(); 51 } 52 } 53 54 /// <summary> 55 /// The mercury color 56 /// </summary> 57 private Color mercuryColor = Color.FromArgb(255, 77, 59); 58 59 /// <summary> 60 /// Gets or sets the color of the mercury. 61 /// </summary> 62 /// <value>The color of the mercury.</value> 63 [Description("水印颜色"), Category("自定义")] 64 public Color MercuryColor 65 { 66 get { return mercuryColor; } 67 set 68 { 69 mercuryColor = value; 70 Refresh(); 71 } 72 } 73 74 /// <summary> 75 /// The minimum value 76 /// </summary> 77 private decimal minValue = 0; 78 /// <summary> 79 /// 左侧刻度最小值 80 /// </summary> 81 /// <value>The minimum value.</value> 82 [Description("左侧刻度最小值"), Category("自定义")] 83 public decimal MinValue 84 { 85 get { return minValue; } 86 set 87 { 88 minValue = value; 89 Refresh(); 90 } 91 } 92 93 /// <summary> 94 /// The maximum value 95 /// </summary> 96 private decimal maxValue = 100; 97 /// <summary> 98 /// 左侧刻度最大值 99 /// </summary> 100 /// <value>The maximum value.</value> 101 [Description("左侧刻度最大值"), Category("自定义")] 102 public decimal MaxValue 103 { 104 get { return maxValue; } 105 set 106 { 107 maxValue = value; 108 Refresh(); 109 } 110 } 111 112 /// <summary> 113 /// The m value 114 /// </summary> 115 private decimal m_value = 10; 116 /// <summary> 117 /// 左侧刻度值 118 /// </summary> 119 /// <value>The value.</value> 120 [Description("左侧刻度值"), Category("自定义")] 121 public decimal Value 122 { 123 get { return m_value; } 124 set 125 { 126 m_value = value; 127 Refresh(); 128 } 129 } 130 131 /// <summary> 132 /// The split count 133 /// </summary> 134 private int splitCount = 0; 135 /// <summary> 136 /// 刻度分隔份数 137 /// </summary> 138 /// <value>The split count.</value> 139 [Description("刻度分隔份数"), Category("自定义")] 140 public int SplitCount 141 { 142 get { return splitCount; } 143 set 144 { 145 if (value <= 0) 146 return; 147 splitCount = value; 148 Refresh(); 149 } 150 } 151 152 /// <summary> 153 /// 获取或设置控件显示的文字的字体。 154 /// </summary> 155 /// <value>The font.</value> 156 /// <PermissionSet> 157 /// <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 158 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 159 /// <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" /> 160 /// <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 161 /// </PermissionSet> 162 [Description("获取或设置控件显示的文字的字体"), Category("自定义")] 163 public override Font Font 164 { 165 get 166 { 167 return base.Font; 168 } 169 set 170 { 171 base.Font = value; 172 Refresh(); 173 } 174 } 175 176 /// <summary> 177 /// 获取或设置控件的前景色。 178 /// </summary> 179 /// <value>The color of the fore.</value> 180 /// <PermissionSet> 181 /// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" /> 182 /// </PermissionSet> 183 [Description("获取或设置控件的文字及刻度颜色"), Category("自定义")] 184 public override System.Drawing.Color ForeColor 185 { 186 get 187 { 188 return base.ForeColor; 189 } 190 set 191 { 192 base.ForeColor = value; 193 Refresh(); 194 } 195 } 196 197 /// <summary> 198 /// The left temperature unit 199 /// </summary> 200 private TemperatureUnit leftTemperatureUnit = TemperatureUnit.C; 201 /// <summary> 202 /// 左侧刻度单位,不可为none 203 /// </summary> 204 /// <value>The left temperature unit.</value> 205 [Description("左侧刻度单位,不可为none"), Category("自定义")] 206 public TemperatureUnit LeftTemperatureUnit 207 { 208 get { return leftTemperatureUnit; } 209 set 210 { 211 if (value == TemperatureUnit.None) 212 return; 213 leftTemperatureUnit = value; 214 Refresh(); 215 } 216 } 217 218 /// <summary> 219 /// The right temperature unit 220 /// </summary> 221 private TemperatureUnit rightTemperatureUnit = TemperatureUnit.C; 222 /// <summary> 223 /// 右侧刻度单位,当为none时,不显示 224 /// </summary> 225 /// <value>The right temperature unit.</value> 226 [Description("右侧刻度单位,当为none时,不显示"), Category("自定义")] 227 public TemperatureUnit RightTemperatureUnit 228 { 229 get { return rightTemperatureUnit; } 230 set 231 { 232 rightTemperatureUnit = value; 233 Refresh(); 234 } 235 } 236 237 /// <summary> 238 /// The m rect working 239 /// </summary> 240 Rectangle m_rectWorking; 241 /// <summary> 242 /// The m rect left 243 /// </summary> 244 Rectangle m_rectLeft; 245 /// <summary> 246 /// The m rect right 247 /// </summary> 248 Rectangle m_rectRight; 249 /// <summary> 250 /// Initializes a new instance of the <see cref="UCThermometer"/> class. 251 /// </summary> 252 public UCThermometer() 253 { 254 this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 255 this.SetStyle(ControlStyles.DoubleBuffer, true); 256 this.SetStyle(ControlStyles.ResizeRedraw, true); 257 this.SetStyle(ControlStyles.Selectable, true); 258 this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); 259 this.SetStyle(ControlStyles.UserPaint, true); 260 this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; 261 this.SizeChanged += UCThermometer_SizeChanged; 262 this.Size = new Size(70, 200); 263 } 264 265 /// <summary> 266 /// Handles the SizeChanged event of the UCThermometer control. 267 /// </summary> 268 /// <param name="sender">The source of the event.</param> 269 /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> 270 void UCThermometer_SizeChanged(object sender, EventArgs e) 271 { 272 m_rectWorking = new Rectangle(this.Width / 2 - this.Width / 8, this.Width / 4, this.Width / 4, this.Height - this.Width / 2); 273 m_rectLeft = new Rectangle(0, m_rectWorking.Top + m_rectWorking.Width / 2, (this.Width - this.Width / 4) / 2 - 2, m_rectWorking.Height - m_rectWorking.Width * 2); 274 m_rectRight = new Rectangle(this.Width - (this.Width - this.Width / 4) / 2 + 2, m_rectWorking.Top + m_rectWorking.Width / 2, (this.Width - this.Width / 4) / 2 - 2, m_rectWorking.Height - m_rectWorking.Width * 2); 275 } 276 277 /// <summary> 278 /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。 279 /// </summary> 280 /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param> 281 protected override void OnPaint(PaintEventArgs e) 282 { 283 base.OnPaint(e); 284 var g = e.Graphics; 285 g.SetGDIHigh(); 286 287 //玻璃管管 288 GraphicsPath path = new GraphicsPath(); 289 path.AddLine(m_rectWorking.Left, m_rectWorking.Bottom, m_rectWorking.Left, m_rectWorking.Top + m_rectWorking.Width / 2); 290 path.AddArc(new Rectangle(m_rectWorking.Left, m_rectWorking.Top, m_rectWorking.Width, m_rectWorking.Width), 180, 180); 291 path.AddLine(m_rectWorking.Right, m_rectWorking.Top + m_rectWorking.Width / 2, m_rectWorking.Right, m_rectWorking.Bottom); 292 path.CloseAllFigures(); 293 g.FillPath(new SolidBrush(glassTubeColor), path); 294 295 //底部 296 var rectDi = new Rectangle(this.Width / 2 - m_rectWorking.Width, m_rectWorking.Bottom - m_rectWorking.Width - 2, m_rectWorking.Width * 2, m_rectWorking.Width * 2); 297 g.FillEllipse(new SolidBrush(glassTubeColor), rectDi); 298 g.FillEllipse(new SolidBrush(mercuryColor), new Rectangle(rectDi.Left + 4, rectDi.Top + 4, rectDi.Width - 8, rectDi.Height - 8)); 299 300 //刻度 301 decimal decSplit = (maxValue - minValue) / splitCount; 302 decimal decSplitHeight = m_rectLeft.Height / splitCount; 303 for (int i = 0; i <= splitCount; i++) 304 { 305 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Left + 2, (float)(m_rectLeft.Bottom - decSplitHeight * i)), new PointF(m_rectLeft.Right, (float)(m_rectLeft.Bottom - decSplitHeight * i))); 306 307 var valueLeft = (minValue + decSplit * i).ToString("0.##"); 308 var sizeLeft = g.MeasureString(valueLeft, Font); 309 g.DrawString(valueLeft, Font, new SolidBrush(ForeColor), new PointF(m_rectLeft.Left, m_rectLeft.Bottom - (float)decSplitHeight * i - sizeLeft.Height - 1)); 310 311 if (rightTemperatureUnit != TemperatureUnit.None) 312 { 313 g.DrawLine(new Pen(new SolidBrush(Color.Black), 1), new PointF(m_rectRight.Left + 2, (float)(m_rectRight.Bottom - decSplitHeight * i)), new PointF(m_rectRight.Right, (float)(m_rectRight.Bottom - decSplitHeight * i))); 314 var valueRight = GetRightValue(minValue + decSplit * i).ToString("0.##"); 315 var sizeRight = g.MeasureString(valueRight, Font); 316 g.DrawString(valueRight, Font, new SolidBrush(ForeColor), new PointF(m_rectRight.Right - sizeRight.Width - 1, m_rectRight.Bottom - (float)decSplitHeight * i - sizeRight.Height - 1)); 317 } 318 if (i != splitCount) 319 { 320 if (decSplitHeight > 40) 321 { 322 var decSp1 = decSplitHeight / 10; 323 for (int j = 1; j < 10; j++) 324 { 325 if (j == 5) 326 { 327 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Right - 10, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectLeft.Right, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 328 if (rightTemperatureUnit != TemperatureUnit.None) 329 { 330 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectRight.Left + 10, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectRight.Left, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 331 } 332 } 333 else 334 { 335 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Right - 5, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectLeft.Right, (m_rectLeft.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 336 if (rightTemperatureUnit != TemperatureUnit.None) 337 { 338 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectRight.Left + 5, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j))), new PointF(m_rectRight.Left, (m_rectRight.Bottom - (float)decSplitHeight * i - ((float)decSp1 * j)))); 339 } 340 } 341 } 342 } 343 else if (decSplitHeight > 10) 344 { 345 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectLeft.Right - 5, (m_rectLeft.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2)), new PointF(m_rectLeft.Right, (m_rectLeft.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2))); 346 if (rightTemperatureUnit != TemperatureUnit.None) 347 { 348 g.DrawLine(new Pen(new SolidBrush(ForeColor), 1), new PointF(m_rectRight.Left + 5, (m_rectRight.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2)), new PointF(m_rectRight.Left, (m_rectRight.Bottom - (float)decSplitHeight * i - (float)decSplitHeight / 2))); 349 } 350 } 351 } 352 } 353 //单位 354 string strLeftUnit = GetUnitChar(leftTemperatureUnit); 355 g.DrawString(strLeftUnit, Font, new SolidBrush(ForeColor), new PointF(m_rectLeft.Left + 2, 2)); 356 if (rightTemperatureUnit != TemperatureUnit.None) 357 { 358 string strRightUnit = GetUnitChar(rightTemperatureUnit); 359 var rightSize = g.MeasureString(strRightUnit, Font); 360 g.DrawString(strRightUnit, Font, new SolidBrush(ForeColor), new PointF(m_rectRight.Right - 2 - rightSize.Width, 2)); 361 } 362 //值 363 float fltHeightValue = (float)(Value / (maxValue - minValue) * m_rectLeft.Height); 364 RectangleF rectValue = new RectangleF(m_rectWorking.Left + 4, m_rectLeft.Top + (m_rectLeft.Height - fltHeightValue), m_rectWorking.Width - 8, fltHeightValue + (m_rectWorking.Height - m_rectWorking.Width / 2 - m_rectLeft.Height)); 365 g.FillRectangle(new SolidBrush(mercuryColor), rectValue); 366 367 368 var sizeValue = g.MeasureString(m_value.ToString("0.##"), Font); 369 g.DrawString(m_value.ToString("0.##"), Font, new SolidBrush(Color.White), new PointF(rectDi.Left + (rectDi.Width - sizeValue.Width) / 2, rectDi.Top + (rectDi.Height - sizeValue.Height) / 2 + 1)); 370 } 371 372 private string GetUnitChar(TemperatureUnit unit) 373 { 374 string strUnit = "℃"; 375 switch (unit) 376 { 377 case TemperatureUnit.C: 378 strUnit = "℃"; 379 break; 380 case TemperatureUnit.F: 381 strUnit = "℉"; 382 break; 383 case TemperatureUnit.K: 384 strUnit = "K"; 385 break; 386 case TemperatureUnit.R: 387 strUnit = "°R"; 388 break; 389 case TemperatureUnit.Re: 390 strUnit = "°Re"; 391 break; 392 } 393 return strUnit; 394 } 395 396 private decimal GetRightValue(decimal decValue) 397 { 398 //先将左侧的换算为摄氏度 399 var dec = decValue; 400 switch (leftTemperatureUnit) 401 { 402 case TemperatureUnit.F: 403 dec = (decValue - 32) / (9M / 5M); 404 break; 405 case TemperatureUnit.K: 406 dec = decValue - 273; 407 break; 408 case TemperatureUnit.R: 409 dec = decValue / (5M / 9M) - 273.15M; 410 break; 411 case TemperatureUnit.Re: 412 dec = decValue / 1.25M; 413 break; 414 default: 415 break; 416 } 417 418 switch (rightTemperatureUnit) 419 { 420 case TemperatureUnit.C: 421 return dec; 422 case TemperatureUnit.F: 423 return 9M / 5M * dec + 32; 424 case TemperatureUnit.K: 425 return dec + 273; 426 case TemperatureUnit.R: 427 return (dec + 273.15M) * (5M / 9M); 428 case TemperatureUnit.Re: 429 return dec * 1.25M; 430 } 431 return decValue; 432 } 433 } 434 435 /// <summary> 436 /// Enum TemperatureUnit 437 /// </summary> 438 public enum TemperatureUnit 439 { 440 /// <summary> 441 /// 不显示 442 /// </summary> 443 None, 444 /// <summary> 445 /// 摄氏度 446 /// </summary> 447 C, 448 /// <summary> 449 /// 华氏度 450 /// </summary> 451 F, 452 /// <summary> 453 /// 开氏度 454 /// </summary> 455 K, 456 /// <summary> 457 /// 兰氏度 458 /// </summary> 459 R, 460 /// <summary> 461 /// 列氏度 462 /// </summary> 463 Re 464 } 465 }
View Code
最后的话
如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧