(五十四)c#Winform自定義控制項-儀錶盤

来源:https://www.cnblogs.com/bfyx/archive/2019/09/04/11457234.html
-Advertisement-
Play Games

前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...


前提

入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。

GitHub:https://github.com/kwwwvagaa/NetWinformControl

碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

如果覺得寫的還行,請點個 star 支持一下吧

歡迎前來交流探討: 企鵝群568015492 企鵝群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,
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 什麼是值類型? 值類型: 就是非類類型,委托類型,介面類型,string類型的類型稱為值類型。 引用類型類型:就是類類型,委托類型,介面類型,string類型稱為引用類型。 值類型與引用類型的賦值問題。。。。 值類型的賦值:值類型之間的賦值是創建一個副本,兩個完全獨立的變數存儲一個值。 輸出結果:1 ...
  • 前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...
  • 項目添加XML文件:FaceXml.xml,並複製到輸出目錄 FaceXml.xml <?xml version="1.0" encoding="utf-8"?> <faces> <face> <faceid></faceid> <facebyte>/facebyte> </face></faces ...
  • 場景 Winform中實現讀取xml配置文件並動態配置ZedGraph的RadioGroup的選項: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100540708 在上面實現了將RadioGroup的選項根據配置文件動態配置後 ...
  • 內容安全策略(CSP)是一個增加的安全層,可幫助檢測和緩解某些類型的攻擊,包括跨站點腳本(XSS)和數據註入攻擊。這些攻擊用於從數據竊取到站點破壞或惡意軟體分發的所有內容(深入CSP) 簡而言之,CSP是網頁控制允許載入哪些資源的一種方式。例如,頁面可以顯式聲明允許從中載入JavaScript,CS ...
  • 場景 Winform中對ZedGraph的RadioGroup進行數據源綁定,即通過代碼添加選項: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100540152 Winform中自定義xml配置文件後對節點進行讀取與寫入: h ...
  • 場景 在尋找設置RadioGroup的選項時沒有找到相關博客,在DevExpress的官網找到 怎樣給其添加選項。 DevExpress官網教程: https://documentation.devexpress.com/WindowsForms/DevExpress.XtraEditors.Rad ...
  • 場景 Winform中自定義xml配置文件後對節點進行讀取與寫入: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100532137 在上面已經對xml配置文件對節點能進行讀取與寫入之後 ,實現對節點元素的 添加與刪除。 關註公眾 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...