欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

(五十四)c#Winform自定义控件-仪表盘

程序员文章站 2022-05-07 11:51:37
前提 入行已经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

目录

用处及效果

(五十四)c#Winform自定义控件-仪表盘

准备工作

依然使用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 }

 

 

最后的话

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