(四十五)c#Winform自定義控件-水波圖表-HZHControls

官網

http://www.hzhcontrols.comhtml

前提

入行已經7,8年了,一直想作一套漂亮點的自定義控件,因而就有了本系列文章。git

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

碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_control.gitc#

若是以爲寫的還行,請點個 star 支持一下吧緩存

歡迎前來交流探討: 企鵝羣568015492 企鵝羣568015492ide

麻煩博客下方點個【推薦】,謝謝函數

NuGet

Install-Package HZH_Controls

目錄

http://www.javashuo.com/article/p-hacmmtru-mw.htmlthis

用處及效果

準備工做

這個用到GDI+畫的,請先了解一下GDI+spa

還有用到了基類控件UCControlBase來控制圓角和背景色,若是還不瞭解請移步查看3d

(一)c#Winform自定義控件-基類控件

開始

添加一個類UCWaveWithSource ,繼承UCControlBase

添加屬性

private int m_waveActualWidth = 50; private int m_waveWidth = 50; [Description("波形寬度"), Category("自定義")] public int WaveWidth { get { return m_waveWidth; } set { if (value <= 0) return; m_waveWidth = value; ResetWaveCount(); Refresh(); } } private int m_sleepTime = 1000; /// <summary>
        /// 波運行速度(運行時間間隔,毫秒) /// </summary>
        [Description("運行速度(運行時間間隔,毫秒)"), Category("自定義")] public int SleepTime { get { return m_sleepTime; } set { if (value <= 0) return; m_sleepTime = value; if (timer != null) { timer.Enabled = false; timer.Interval = value; timer.Enabled = true; } } } private float m_lineTension = 0.5f; /// <summary>
        /// 線彎曲程度 /// </summary>
        [Description("線彎曲程度(0-1)"), Category("自定義")] public float LineTension { get { return m_lineTension; } set { if (!(value >= 0 && value <= 1)) { return; } m_lineTension = value; Refresh(); } } private Color m_lineColor = Color.FromArgb(150, 73, 119, 232); [Description("曲線顏色"), Category("自定義")] public Color LineColor { get { return m_lineColor; } set { m_lineColor = value; Refresh(); } } private Color m_gridLineColor = Color.FromArgb(50, 73, 119, 232); [Description("網格線顏色"), Category("自定義")] public Color GridLineColor { get { return m_gridLineColor; } set { m_gridLineColor = value; Refresh(); } } private Color m_gridLineTextColor = Color.FromArgb(150, 73, 119, 232); [Description("網格文本顏色"), Category("自定義")] public Color GridLineTextColor { get { return m_gridLineTextColor; } set { m_gridLineTextColor = value; Refresh(); } } public override Font Font { get { return base.Font; } set { base.Font = value; } } /// <summary>
        /// 數據源,用以緩存全部須要顯示的數據 /// </summary>
        List<KeyValuePair<string, double>> m_dataSource = new List<KeyValuePair<string, double>>(); /// <summary>
        /// 當前須要顯示的數據 /// </summary>
        List<KeyValuePair<string, double>> m_currentSource = new List<KeyValuePair<string, double>>(); Timer timer = new Timer(); /// <summary>
        /// 畫圖區域 /// </summary>
 Rectangle m_drawRect; int m_waveCount = 0;

構造函數中初始化一下樣式

 1         public UCWaveWithSource()  2  {  3             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);  4             this.SetStyle(ControlStyles.DoubleBuffer, true);  5             this.SetStyle(ControlStyles.ResizeRedraw, true);  6             this.SetStyle(ControlStyles.Selectable, true);  7             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);  8             this.SetStyle(ControlStyles.UserPaint, true);  9 
10             this.SizeChanged += UCWaveWithSource_SizeChanged; 11             this.IsShowRect = true; 12             this.RectColor = Color.FromArgb(232, 232, 232); 13             this.FillColor = Color.FromArgb(197, 229, 250); 14             this.RectWidth = 1; 15             this.ConerRadius = 10; 16             this.IsRadius = true; 17             this.Size = new Size(300, 200); 18 
19             timer.Interval = m_sleepTime; 20             timer.Tick += timer_Tick; 21             this.VisibleChanged += UCWave_VisibleChanged; 22         }

一個數據添加的函數

1  /// <summary>
2         /// 添加須要顯示的數據 3         /// </summary>
4         /// <param name="key">名稱</param>
5         /// <param name="value"></param>
6         public void AddSource(string key, double value) 7  { 8             m_dataSource.Add(new KeyValuePair<string, double>(key, value)); 9         }

重繪

 1 protected override void OnPaint(PaintEventArgs e)  2  {  3             base.OnPaint(e);  4             var g = e.Graphics;  5  g.SetGDIHigh();  6 
 7             int intLineSplit = m_drawRect.Height / 4;  8             for (int i = 0; i <= 4; i++)  9  { 10                 var pen = new Pen(new SolidBrush(m_gridLineColor), 1); 11                 // pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
12                 g.DrawLine(pen, m_drawRect.Left, m_drawRect.Bottom - 1 - i * intLineSplit, m_drawRect.Right, m_drawRect.Bottom - 1 - i * intLineSplit); 13  } 14 
15             if (m_currentSource == null || m_currentSource.Count <= 0) 16  { 17                 for (int i = 0; i <= 4; i++) 18  { 19                     string strText = (100 / 4 * i).ToString(); 20                     System.Drawing.SizeF _numSize = g.MeasureString(strText, this.Font); 21                     g.DrawString(strText, Font, new SolidBrush(m_gridLineTextColor), m_drawRect.Left - _numSize.Width - 1, m_drawRect.Bottom - 1 - i * intLineSplit - (_numSize.Height / 2)); 22  } 23                 return; 24  } 25             List<Point> lst1 = new List<Point>(); 26             double dblValue = m_currentSource.Max(p => p.Value); 27             int intValue = (int)dblValue; 28             int intDivisor = ("1".PadRight(intValue.ToString().Length - 1, '0')).ToInt(); 29             if (intDivisor < 100) 30                 intDivisor = 100; 31             int intTop = intValue; 32             if (intValue % intDivisor != 0) 33  { 34                 intTop = (intValue / intDivisor + 1) * intDivisor; 35  } 36             if (intTop == 0) 37                 intTop = 100; 38 
39             for (int i = 0; i <= 4; i++) 40  { 41                 string strText = (intTop / 4 * i).ToString(); 42                 System.Drawing.SizeF _numSize = g.MeasureString(strText, this.Font); 43                 g.DrawString(strText, Font, new SolidBrush(m_gridLineTextColor), m_drawRect.Left - _numSize.Width - 1, m_drawRect.Bottom - 1 - i * intLineSplit - (_numSize.Height / 2)); 44  } 45 
46             int intEndX = 0; 47             int intEndY = 0; 48             for (int i = 0; i < m_currentSource.Count; i++) 49  { 50                 intEndX = i * m_waveActualWidth + m_drawRect.X; 51                 intEndY = m_drawRect.Bottom - 1 - (int)(m_currentSource[i].Value / intTop * m_drawRect.Height); 52                 lst1.Add(new Point(intEndX, intEndY)); 53                 if (!string.IsNullOrEmpty(m_currentSource[i].Key)) 54  { 55                     System.Drawing.SizeF _numSize = g.MeasureString(m_currentSource[i].Key, this.Font); 56                     int txtX = intEndX - (int)(_numSize.Width / 2) + 1; 57                     g.DrawString(m_currentSource[i].Key, Font, new SolidBrush(m_gridLineTextColor), new PointF(txtX, m_drawRect.Bottom + 5)); 58  } 59  } 60 
61             int intFirstY = m_drawRect.Bottom - 1 - (int)(m_currentSource[0].Value / intTop * m_drawRect.Height); 62 
63 
64             GraphicsPath path1 = new GraphicsPath(); 65  path1.AddCurve(lst1.ToArray(), m_lineTension); 66             g.DrawPath(new Pen(new SolidBrush(m_lineColor), 1), path1); 67 
68         }

輔助函數

 1 /// <summary>
 2         /// 獲得當前須要畫圖的數據  3         /// </summary>
 4         /// <returns></returns>
 5         private List<KeyValuePair<string, double>> GetCurrentList()  6  {  7             if (m_dataSource.Count < m_waveCount)  8  {  9                 int intCount = m_waveCount - m_dataSource.Count; 10                 for (int i = 0; i < intCount; i++) 11  { 12                     m_dataSource.Add(new KeyValuePair<string, double>("", 0)); 13  } 14  } 15 
16             var lst = m_dataSource.GetRange(0, m_waveCount); 17             if (lst.Count == 1) 18                 lst.Insert(0, new KeyValuePair<string, double>("", 0)); 19             return lst; 20  } 21 
22         /// <summary>
23         /// 計算須要顯示的個數 24         /// </summary>
25         private void ResetWaveCount() 26  { 27             m_waveCount = m_drawRect.Width / m_waveWidth; 28             m_waveActualWidth = m_waveWidth + (m_drawRect.Width % m_waveWidth) / m_waveCount; 29             m_waveCount++; 30             if (m_dataSource.Count < m_waveCount) 31  { 32                 int intCount = m_waveCount - m_dataSource.Count; 33                 for (int i = 0; i < intCount; i++) 34  { 35                     m_dataSource.Insert(0, new KeyValuePair<string, double>("", 0)); 36  } 37  } 38         }

完整代碼

 1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Drawing;  5 using System.Drawing.Drawing2D;  6 using System.Linq;  7 using System.Text;  8 using System.Windows.Forms;  9 
 10 namespace HZH_Controls.Controls  11 {  12     public class UCWaveWithSource : UCControlBase  13  {  14         private int m_waveActualWidth = 50;  15 
 16         private int m_waveWidth = 50;  17 
 18         [Description("波形寬度"), Category("自定義")]  19         public int WaveWidth  20  {  21             get { return m_waveWidth; }  22             set
 23  {  24                 if (value <= 0)  25                     return;  26                 m_waveWidth = value;  27  ResetWaveCount();  28  Refresh();  29  }  30  }  31 
 32         private int m_sleepTime = 1000;  33         /// <summary>
 34         /// 波運行速度(運行時間間隔,毫秒)  35         /// </summary>
 36         [Description("運行速度(運行時間間隔,毫秒)"), Category("自定義")]  37         public int SleepTime  38  {  39             get { return m_sleepTime; }  40             set
 41  {  42                 if (value <= 0)  43                     return;  44                 m_sleepTime = value;  45                 if (timer != null)  46  {  47                     timer.Enabled = false;  48                     timer.Interval = value;  49                     timer.Enabled = true;  50  }  51  }  52  }  53 
 54         private float m_lineTension = 0.5f;  55         /// <summary>
 56         /// 線彎曲程度  57         /// </summary>
 58         [Description("線彎曲程度(0-1)"), Category("自定義")]  59         public float LineTension  60  {  61             get { return m_lineTension; }  62             set
 63  {  64                 if (!(value >= 0 && value <= 1))  65  {  66                     return;  67  }  68                 m_lineTension = value;  69  Refresh();  70  }  71  }  72 
 73         private Color m_lineColor = Color.FromArgb(150, 73, 119, 232);  74 
 75         [Description("曲線顏色"), Category("自定義")]  76         public Color LineColor  77  {  78             get { return m_lineColor; }  79             set
 80  {  81                 m_lineColor = value;  82  Refresh();  83 
 84  }  85  }  86 
 87         private Color m_gridLineColor = Color.FromArgb(50, 73, 119, 232);  88 
 89         [Description("網格線顏色"), Category("自定義")]  90         public Color GridLineColor  91  {  92             get { return m_gridLineColor; }  93             set
 94  {  95                 m_gridLineColor = value;  96  Refresh();  97  }  98  }  99 
100         private Color m_gridLineTextColor = Color.FromArgb(150, 73, 119, 232); 101 
102         [Description("網格文本顏色"), Category("自定義")] 103         public Color GridLineTextColor 104  { 105             get { return m_gridLineTextColor; } 106             set
107  { 108                 m_gridLineTextColor = value; 109  Refresh(); 110  } 111  } 112 
113         public override Font Font 114  { 115             get
116  { 117                 return base.Font; 118  } 119             set
120  { 121                 base.Font = value; 122  } 123  } 124         /// <summary>
125         /// 數據源,用以緩存全部須要顯示的數據 126         /// </summary>
127         List<KeyValuePair<string, double>> m_dataSource = new List<KeyValuePair<string, double>>(); 128         /// <summary>
129         /// 當前須要顯示的數據 130         /// </summary>
131         List<KeyValuePair<string, double>> m_currentSource = new List<KeyValuePair<string, double>>(); 132         Timer timer = new Timer(); 133         /// <summary>
134         /// 畫圖區域 135         /// </summary>
136  Rectangle m_drawRect; 137 
138         int m_waveCount = 0; 139         public UCWaveWithSource() 140  { 141             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); 142             this.SetStyle(ControlStyles.DoubleBuffer, true); 143             this.SetStyle(ControlStyles.ResizeRedraw, true); 144             this.SetStyle(ControlStyles.Selectable, true); 145             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true); 146             this.SetStyle(ControlStyles.UserPaint, true); 147 
148             this.SizeChanged += UCWaveWithSource_SizeChanged; 149             this.IsShowRect = true; 150             this.RectColor = Color.FromArgb(232, 232, 232); 151             this.FillColor = Color.FromArgb(197, 229, 250); 152             this.RectWidth = 1; 153             this.ConerRadius = 10; 154             this.IsRadius = true; 155             this.Size = new Size(300, 200); 156 
157             timer.Interval = m_sleepTime; 158             timer.Tick += timer_Tick; 159             this.VisibleChanged += UCWave_VisibleChanged; 160  } 161 
162      
163         /// <summary>
164         /// 添加須要顯示的數據 165         /// </summary>
166         /// <param name="key">名稱</param>
167         /// <param name="value"></param>
168         public void AddSource(string key, double value) 169  { 170             m_dataSource.Add(new KeyValuePair<string, double>(key, value)); 171  } 172 
173         void UCWave_VisibleChanged(object sender, EventArgs e) 174  { 175             if (!DesignMode) 176  { 177                 timer.Enabled = this.Visible; 178  } 179  } 180 
181         void timer_Tick(object sender, EventArgs e) 182  { 183             m_currentSource = GetCurrentList(); 184             m_dataSource.RemoveAt(0); 185             this.Refresh(); 186  } 187         void UCWaveWithSource_SizeChanged(object sender, EventArgs e) 188  { 189             m_drawRect = new Rectangle(60, 20, this.Width - 80, this.Height - 60); 190  ResetWaveCount(); 191  } 192 
193         protected override void OnPaint(PaintEventArgs e) 194  { 195             base.OnPaint(e); 196             var g = e.Graphics; 197  g.SetGDIHigh(); 198 
199             int intLineSplit = m_drawRect.Height / 4; 200             for (int i = 0; i <= 4; i++) 201  { 202                 var pen = new Pen(new SolidBrush(m_gridLineColor), 1); 203                 // pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
204                 g.DrawLine(pen, m_drawRect.Left, m_drawRect.Bottom - 1 - i * intLineSplit, m_drawRect.Right, m_drawRect.Bottom - 1 - i * intLineSplit); 205  } 206 
207             if (m_currentSource == null || m_currentSource.Count <= 0) 208  { 209                 for (int i = 0; i <= 4; i++) 210  { 211                     string strText = (100 / 4 * i).ToString(); 212                     System.Drawing.SizeF _numSize = g.MeasureString(strText, this.Font); 213                     g.DrawString(strText, Font, new SolidBrush(m_gridLineTextColor), m_drawRect.Left - _numSize.Width - 1, m_drawRect.Bottom - 1 - i * intLineSplit - (_numSize.Height / 2)); 214  } 215                 return; 216  } 217             List<Point> lst1 = new List<Point>(); 218             double dblValue = m_currentSource.Max(p => p.Value); 219             int intValue = (int)dblValue; 220             int intDivisor = ("1".PadRight(intValue.ToString().Length - 1, '0')).ToInt(); 221             if (intDivisor < 100) 222                 intDivisor = 100; 223             int intTop = intValue; 224             if (intValue % intDivisor != 0) 225  { 226                 intTop = (intValue / intDivisor + 1) * intDivisor; 227  } 228             if (intTop == 0) 229                 intTop = 100; 230 
231             for (int i = 0; i <= 4; i++) 232  { 233                 string strText = (intTop / 4 * i).ToString(); 234                 System.Drawing.SizeF _numSize = g.MeasureString(strText, this.Font); 235                 g.DrawString(strText, Font, new SolidBrush(m_gridLineTextColor), m_drawRect.Left - _numSize.Width - 1, m_drawRect.Bottom - 1 - i * intLineSplit - (_numSize.Height / 2)); 236  } 237 
238             int intEndX = 0; 239             int intEndY = 0; 240             for (int i = 0; i < m_currentSource.Count; i++) 241  { 242                 intEndX = i * m_waveActualWidth + m_drawRect.X; 243                 intEndY = m_drawRect.Bottom - 1 - (int)(m_currentSource[i].Value / intTop * m_drawRect.Height); 244                 lst1.Add(new Point(intEndX, intEndY)); 245                 if (!string.IsNullOrEmpty(m_currentSource[i].Key)) 246  { 247                     System.Drawing.SizeF _numSize = g.MeasureString(m_currentSource[i].Key, this.Font); 248                     int txtX = intEndX - (int)(_numSize.Width / 2) + 1; 249                     g.DrawString(m_currentSource[i].Key, Font, new SolidBrush(m_gridLineTextColor), new PointF(txtX, m_drawRect.Bottom + 5)); 250  } 251  } 252 
253             int intFirstY = m_drawRect.Bottom - 1 - (int)(m_currentSource[0].Value / intTop * m_drawRect.Height); 254 
255 
256             GraphicsPath path1 = new GraphicsPath(); 257  path1.AddCurve(lst1.ToArray(), m_lineTension); 258             g.DrawPath(new Pen(new SolidBrush(m_lineColor), 1), path1); 259 
260  } 261         /// <summary>
262         /// 獲得當前須要畫圖的數據 263         /// </summary>
264         /// <returns></returns>
265         private List<KeyValuePair<string, double>> GetCurrentList() 266  { 267             if (m_dataSource.Count < m_waveCount) 268  { 269                 int intCount = m_waveCount - m_dataSource.Count; 270                 for (int i = 0; i < intCount; i++) 271  { 272                     m_dataSource.Add(new KeyValuePair<string, double>("", 0)); 273  } 274  } 275 
276             var lst = m_dataSource.GetRange(0, m_waveCount); 277             if (lst.Count == 1) 278                 lst.Insert(0, new KeyValuePair<string, double>("", 0)); 279             return lst; 280  } 281 
282         /// <summary>
283         /// 計算須要顯示的個數 284         /// </summary>
285         private void ResetWaveCount() 286  { 287             m_waveCount = m_drawRect.Width / m_waveWidth; 288             m_waveActualWidth = m_waveWidth + (m_drawRect.Width % m_waveWidth) / m_waveCount; 289             m_waveCount++; 290             if (m_dataSource.Count < m_waveCount) 291  { 292                 int intCount = m_waveCount - m_dataSource.Count; 293                 for (int i = 0; i < intCount; i++) 294  { 295                     m_dataSource.Insert(0, new KeyValuePair<string, double>("", 0)); 296  } 297  } 298  } 299  } 300 }
View Code

 

最後的話

若是你喜歡的話,請到 https://gitee.com/kwwwvagaa/net_winform_custom_control 點個星星吧

原文出處:https://www.cnblogs.com/bfyx/p/11397997.html

相關文章
相關標籤/搜索