(七十一)c#Winform自定义控件-折线图

前提

入行已经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+相关知识

开始

添加一个类UCCurve 继承自UserControl

添加一些控制属性

复制代码

  1 /// <summary>
  2         /// The value count maximum
  3         /// </summary>
  4         private const int value_count_max = 4096;
  5 
  6         /// <summary>
  7         /// The value maximum left
  8         /// </summary>
  9         private float value_max_left = 100f;
 10 
 11         /// <summary>
 12         /// The value minimum left
 13         /// </summary>
 14         private float value_min_left = 0f;
 15 
 16         /// <summary>
 17         /// The value maximum right
 18         /// </summary>
 19         private float value_max_right = 100f;
 20 
 21         /// <summary>
 22         /// The value minimum right
 23         /// </summary>
 24         private float value_min_right = 0f;
 25 
 26         /// <summary>
 27         /// The value segment
 28         /// </summary>
 29         private int value_Segment = 5;
 30 
 31         /// <summary>
 32         /// The value is abscissa strech
 33         /// </summary>
 34         private bool value_IsAbscissaStrech = false;
 35 
 36         /// <summary>
 37         /// The value strech data count maximum
 38         /// </summary>
 39         private int value_StrechDataCountMax = 300;
 40 
 41         /// <summary>
 42         /// The value is render dash line
 43         /// </summary>
 44         private bool value_IsRenderDashLine = true;
 45 
 46         /// <summary>
 47         /// The text format
 48         /// </summary>
 49         private string textFormat = "HH:mm";
 50 
 51         /// <summary>
 52         /// The value interval abscissa text
 53         /// </summary>
 54         private int value_IntervalAbscissaText = 100;
 55 
 56         /// <summary>
 57         /// The random
 58         /// </summary>
 59         private Random random = null;
 60 
 61         /// <summary>
 62         /// The value title
 63         /// </summary>
 64         private string value_title = "";
 65 
 66         /// <summary>
 67         /// The left right
 68         /// </summary>
 69         private int leftRight = 50;
 70 
 71         /// <summary>
 72         /// Up dowm
 73         /// </summary>
 74         private int upDowm = 50;
 75 
 76         /// <summary>
 77         /// The data list
 78         /// </summary>
 79         private Dictionary<string, CurveItem> data_list = null;
 80 
 81         /// <summary>
 82         /// The data text
 83         /// </summary>
 84         private string[] data_text = null;
 85 
 86         /// <summary>
 87         /// The auxiliary lines
 88         /// </summary>
 89         private List<AuxiliaryLine> auxiliary_lines;
 90 
 91         /// <summary>
 92         /// The auxiliary labels
 93         /// </summary>
 94         private List<AuxiliaryLable> auxiliary_Labels;
 95 
 96         /// <summary>
 97         /// The mark texts
 98         /// </summary>
 99         private List<MarkText> MarkTexts;
100 
101         /// <summary>
102         /// The font size9
103         /// </summary>
104         private Font font_size9 = null;
105 
106         /// <summary>
107         /// The font size12
108         /// </summary>
109         private Font font_size12 = null;
110 
111         /// <summary>
112         /// The brush deep
113         /// </summary>
114         private Brush brush_deep = null;
115 
116         /// <summary>
117         /// The pen normal
118         /// </summary>
119         private Pen pen_normal = null;
120 
121         /// <summary>
122         /// The pen dash
123         /// </summary>
124         private Pen pen_dash = null;
125 
126         /// <summary>
127         /// The color normal
128         /// </summary>
129         private Color color_normal = Color.DeepPink;
130 
131         /// <summary>
132         /// The color deep
133         /// </summary>
134         private Color color_deep = Color.DimGray;
135 
136         /// <summary>
137         /// The color dash
138         /// </summary>
139         private Color color_dash = Color.FromArgb(232, 232, 232);
140 
141         /// <summary>
142         /// The color mark font
143         /// </summary>
144         private Color color_mark_font = Color.DodgerBlue;
145 
146         /// <summary>
147         /// The brush mark font
148         /// </summary>
149         private Brush brush_mark_font = Brushes.DodgerBlue;
150 
151         /// <summary>
152         /// The format left
153         /// </summary>
154         private StringFormat format_left = null;
155 
156         /// <summary>
157         /// The format right
158         /// </summary>
159         private StringFormat format_right = null;
160 
161         /// <summary>
162         /// The format center
163         /// </summary>
164         private StringFormat format_center = null;
165 
166         /// <summary>
167         /// The is render right coordinate
168         /// </summary>
169         private bool isRenderRightCoordinate = true;
170 
171         /// <summary>
172         /// The curve name width
173         /// </summary>
174         private int curveNameWidth = 100;
175 
176         /// <summary>
177         /// The components
178         /// </summary>
179         private IContainer components = null;
180 
181         /// <summary>
182         /// 获取或设置控件的背景色。
183         /// </summary>
184         /// <value>The color of the back.</value>
185         /// <PermissionSet>
186         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
187         /// </PermissionSet>
188         [Browsable(true)]
189         [Description("获取或设置控件的背景色")]
190         [Category("自定义")]
191         [DefaultValue(typeof(Color), "Transparent")]
192         [EditorBrowsable(EditorBrowsableState.Always)]
193         public override Color BackColor
194         {
195             get
196             {
197                 return base.BackColor;
198             }
199             set
200             {
201                 base.BackColor = value;
202             }
203         }
204 
205         /// <summary>
206         /// Gets or sets the value maximum left.
207         /// </summary>
208         /// <value>The value maximum left.</value>
209         [Category("自定义")]
210         [Description("获取或设置图形的左纵坐标的最大值,该值必须大于最小值")]
211         [Browsable(true)]
212         [DefaultValue(100f)]
213         public float ValueMaxLeft
214         {
215             get
216             {
217                 return value_max_left;
218             }
219             set
220             {
221                 value_max_left = value;
222                 Invalidate();
223             }
224         }
225 
226         /// <summary>
227         /// Gets or sets the value minimum left.
228         /// </summary>
229         /// <value>The value minimum left.</value>
230         [Category("自定义")]
231         [Description("获取或设置图形的左纵坐标的最小值,该值必须小于最大值")]
232         [Browsable(true)]
233         [DefaultValue(0f)]
234         public float ValueMinLeft
235         {
236             get
237             {
238                 return value_min_left;
239             }
240             set
241             {
242                 value_min_left = value;
243                 Invalidate();
244             }
245         }
246 
247         /// <summary>
248         /// Gets or sets the value maximum right.
249         /// </summary>
250         /// <value>The value maximum right.</value>
251         [Category("自定义")]
252         [Description("获取或设置图形的右纵坐标的最大值,该值必须大于最小值")]
253         [Browsable(true)]
254         [DefaultValue(100f)]
255         public float ValueMaxRight
256         {
257             get
258             {
259                 return value_max_right;
260             }
261             set
262             {
263                 value_max_right = value;
264                 Invalidate();
265             }
266         }
267 
268         /// <summary>
269         /// Gets or sets the value minimum right.
270         /// </summary>
271         /// <value>The value minimum right.</value>
272         [Category("自定义")]
273         [Description("获取或设置图形的右纵坐标的最小值,该值必须小于最大值")]
274         [Browsable(true)]
275         [DefaultValue(0f)]
276         public float ValueMinRight
277         {
278             get
279             {
280                 return value_min_right;
281             }
282             set
283             {
284                 value_min_right = value;
285                 Invalidate();
286             }
287         }
288 
289         /// <summary>
290         /// Gets or sets the value segment.
291         /// </summary>
292         /// <value>The value segment.</value>
293         [Category("自定义")]
294         [Description("获取或设置图形的纵轴分段数")]
295         [Browsable(true)]
296         [DefaultValue(5)]
297         public int ValueSegment
298         {
299             get
300             {
301                 return value_Segment;
302             }
303             set
304             {
305                 value_Segment = value;
306                 Invalidate();
307             }
308         }
309 
310         /// <summary>
311         /// Gets or sets a value indicating whether this instance is abscissa strech.
312         /// </summary>
313         /// <value><c>true</c> if this instance is abscissa strech; otherwise, <c>false</c>.</value>
314         [Category("自定义")]
315         [Description("获取或设置所有的数据是否强制在一个界面里显示")]
316         [Browsable(true)]
317         [DefaultValue(false)]
318         public bool IsAbscissaStrech
319         {
320             get
321             {
322                 return value_IsAbscissaStrech;
323             }
324             set
325             {
326                 value_IsAbscissaStrech = value;
327                 Invalidate();
328             }
329         }
330 
331         /// <summary>
332         /// Gets or sets the strech data count maximum.
333         /// </summary>
334         /// <value>The strech data count maximum.</value>
335         [Category("自定义")]
336         [Description("获取或设置拉伸模式下的最大数据量")]
337         [Browsable(true)]
338         [DefaultValue(300)]
339         public int StrechDataCountMax
340         {
341             get
342             {
343                 return value_StrechDataCountMax;
344             }
345             set
346             {
347                 value_StrechDataCountMax = value;
348                 Invalidate();
349             }
350         }
351 
352         /// <summary>
353         /// Gets or sets a value indicating whether this instance is render dash line.
354         /// </summary>
355         /// <value><c>true</c> if this instance is render dash line; otherwise, <c>false</c>.</value>
356         [Category("自定义")]
357         [Description("获取或设置虚线是否进行显示")]
358         [Browsable(true)]
359         [DefaultValue(true)]
360         public bool IsRenderDashLine
361         {
362             get
363             {
364                 return value_IsRenderDashLine;
365             }
366             set
367             {
368                 value_IsRenderDashLine = value;
369                 Invalidate();
370             }
371         }
372 
373         /// <summary>
374         /// Gets or sets the color lines and text.
375         /// </summary>
376         /// <value>The color lines and text.</value>
377         [Category("自定义")]
378         [Description("获取或设置坐标轴及相关信息文本的颜色")]
379         [Browsable(true)]
380         [DefaultValue(typeof(Color), "DimGray")]
381         public Color ColorLinesAndText
382         {
383             get
384             {
385                 return color_deep;
386             }
387             set
388             {
389                 color_deep = value;
390                 InitializationColor();
391                 Invalidate();
392             }
393         }
394 
395         /// <summary>
396         /// Gets or sets the color dash lines.
397         /// </summary>
398         /// <value>The color dash lines.</value>
399         [Category("自定义")]
400         [Description("获取或设置虚线的颜色")]
401         [Browsable(true)]
402         public Color ColorDashLines
403         {
404             get
405             {
406                 return color_dash;
407             }
408             set
409             {
410                 color_dash = value;
411                 if (pen_dash != null)
412                     pen_dash.Dispose();
413                 pen_dash = new Pen(color_dash);
414                 pen_dash.DashStyle = DashStyle.Custom;
415                 pen_dash.DashPattern = new float[2]
416                 {
417                     5f,
418                     5f
419                 };
420                 Invalidate();
421             }
422         }
423 
424         /// <summary>
425         /// Gets or sets the interval abscissa text.
426         /// </summary>
427         /// <value>The interval abscissa text.</value>
428         [Category("自定义")]
429         [Description("获取或设置纵向虚线的分隔情况,单位为多少个数据")]
430         [Browsable(true)]
431         [DefaultValue(100)]
432         public int IntervalAbscissaText
433         {
434             get
435             {
436                 return value_IntervalAbscissaText;
437             }
438             set
439             {
440                 value_IntervalAbscissaText = value;
441                 Invalidate();
442             }
443         }
444 
445         /// <summary>
446         /// Gets or sets the text add format.
447         /// </summary>
448         /// <value>The text add format.</value>
449         [Category("自定义")]
450         [Description("获取或设置实时数据新增时文本相对应于时间的格式化字符串,默认HH:mm")]
451         [Browsable(true)]
452         [DefaultValue("HH:mm")]
453         public string TextAddFormat
454         {
455             get
456             {
457                 return textFormat;
458             }
459             set
460             {
461                 textFormat = value;
462                 Invalidate();
463             }
464         }
465 
466         /// <summary>
467         /// Gets or sets the title.
468         /// </summary>
469         /// <value>The title.</value>
470         [Category("自定义")]
471         [Description("获取或设置图标的标题信息")]
472         [Browsable(true)]
473         [DefaultValue("")]
474         public string Title
475         {
476             get
477             {
478                 return value_title;
479             }
480             set
481             {
482                 value_title = value;
483                 Invalidate();
484             }
485         }
486 
487         /// <summary>
488         /// Gets or sets a value indicating whether this instance is render right coordinate.
489         /// </summary>
490         /// <value><c>true</c> if this instance is render right coordinate; otherwise, <c>false</c>.</value>
491         [Category("自定义")]
492         [Description("获取或设置是否显示右侧的坐标系信息")]
493         [Browsable(true)]
494         [DefaultValue(true)]
495         public bool IsRenderRightCoordinate
496         {
497             get
498             {
499                 return isRenderRightCoordinate;
500             }
501             set
502             {
503                 isRenderRightCoordinate = value;
504                 Invalidate();
505             }
506         }
507 
508         /// <summary>
509         /// Gets or sets the width of the curve name.
510         /// </summary>
511         /// <value>The width of the curve name.</value>
512         [Browsable(true)]
513         [Description("获取或设置曲线名称的布局宽度")]
514         [Category("自定义")]
515         [DefaultValue(100)]
516         public int CurveNameWidth
517         {
518             get
519             {
520                 return curveNameWidth;
521             }
522             set
523             {
524                 if (value > 10)
525                 {
526                     curveNameWidth = value;
527                 }
528             }
529         }

复制代码

构造函数做一些初始化

复制代码

 1  public UCCurve()
 2         {
 3             InitializeComponent();
 4             random = new Random();
 5             data_list = new Dictionary<string, CurveItem>();
 6             auxiliary_lines = new List<AuxiliaryLine>();
 7             MarkTexts = new List<MarkText>();
 8             auxiliary_Labels = new List<AuxiliaryLable>();
 9             format_left = new StringFormat
10             {
11                 LineAlignment = StringAlignment.Center,
12                 Alignment = StringAlignment.Near
13             };
14             format_right = new StringFormat
15             {
16                 LineAlignment = StringAlignment.Center,
17                 Alignment = StringAlignment.Far
18             };
19             format_center = new StringFormat
20             {
21                 LineAlignment = StringAlignment.Center,
22                 Alignment = StringAlignment.Center
23             };
24             font_size9 = new Font("微软雅黑", 9f);
25             font_size12 = new Font("微软雅黑", 12f);
26             InitializationColor();
27             pen_dash = new Pen(color_deep);
28             pen_dash.DashStyle = DashStyle.Custom;
29             pen_dash.DashPattern = new float[2]
30             {
31                 5f,
32                 5f
33             };
34             SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
35             SetStyle(ControlStyles.ResizeRedraw, true);
36             SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
37             SetStyle(ControlStyles.AllPaintingInWmPaint, true);
38         }

复制代码

重绘

复制代码

  1   protected override void OnPaint(PaintEventArgs e)
  2         {
  3             try
  4             {
  5                 Graphics graphics = e.Graphics;
  6                 graphics.SetGDIHigh();
  7                 if (BackColor != Color.Transparent)
  8                 {
  9                     graphics.Clear(BackColor);
 10                 }
 11                 int width = base.Width;
 12                 int height = base.Height;
 13                 if (width < 120 || height < 60)
 14                 {
 15                     return;
 16                 }
 17                 Point[] array = new Point[4]
 18                 {
 19                     new Point(leftRight - 1, upDowm - 8),
 20                     new Point(leftRight - 1, height - upDowm),
 21                     new Point(width - leftRight, height - upDowm),
 22                     new Point(width - leftRight, upDowm - 8)
 23                 };
 24                 graphics.DrawLine(pen_normal, array[0], array[1]);
 25                 graphics.DrawLine(pen_normal, array[1], array[2]);
 26                 if (isRenderRightCoordinate)
 27                 {
 28                     graphics.DrawLine(pen_normal, array[2], array[3]);
 29                 }
 30 
 31                 if (!string.IsNullOrEmpty(value_title))
 32                 {
 33                     graphics.DrawString(value_title, font_size9, brush_deep, new Rectangle(0, 0, width - 1, 20), format_center);
 34                 }
 35 
 36                 if (data_list.Count > 0)
 37                 {
 38                     float num = leftRight + 10;
 39                     foreach (KeyValuePair<string, CurveItem> item in data_list)
 40                     {
 41                         if (item.Value.Visible)
 42                         {
 43                             var titleSize=graphics.MeasureString(item.Key, Font);
 44                             SolidBrush solidBrush = item.Value.LineRenderVisiable ? new SolidBrush(item.Value.LineColor) : new SolidBrush(Color.FromArgb(80, item.Value.LineColor));
 45                             graphics.FillRectangle(solidBrush, num + 8f, 24f, 20f, 14f);
 46                             graphics.DrawString(item.Key, Font, solidBrush, new PointF(num + 30f, 24f+(14 - titleSize.Height) / 2));
 47                             item.Value.TitleRegion = new RectangleF(num, 24f, 60f, 18f);
 48                             solidBrush.Dispose();
 49                             num += titleSize.Width + 30;
 50                         }
 51                     }
 52                 }
 53 
 54 
 55                 for (int i = 0; i < auxiliary_Labels.Count; i++)
 56                 {
 57                     if (!string.IsNullOrEmpty(auxiliary_Labels[i].Text))
 58                     {
 59                         int num2 = (auxiliary_Labels[i].LocationX > 1f) ? ((int)auxiliary_Labels[i].LocationX) : ((int)(auxiliary_Labels[i].LocationX * (float)width));
 60                         int num3 = (int)graphics.MeasureString(auxiliary_Labels[i].Text, Font).Width + 3;
 61                         Point[] points = new Point[6]
 62                     {
 63                         new Point(num2, 11),
 64                         new Point(num2 + 10, 20),
 65                         new Point(num2 + num3 + 10, 20),
 66                         new Point(num2 + num3 + 10, 0),
 67                         new Point(num2 + 10, 0),
 68                         new Point(num2, 11)
 69                     };
 70                         graphics.FillPolygon(auxiliary_Labels[i].TextBack, points);
 71                         graphics.DrawString(auxiliary_Labels[i].Text, Font, auxiliary_Labels[i].TextBrush, new Rectangle(num2 + 7, 0, num3 + 3, 20), format_center);
 72                     }
 73                 }
 74                 ControlHelper.PaintTriangle(graphics, brush_deep, new Point(leftRight - 1, upDowm - 8), 4, GraphDirection.Upward);
 75                 if (isRenderRightCoordinate)
 76                 {
 77                     ControlHelper.PaintTriangle(graphics, brush_deep, new Point(width - leftRight, upDowm - 8), 4, GraphDirection.Upward);
 78                 }
 79                 for (int j = 0; j < auxiliary_lines.Count; j++)
 80                 {
 81                     if (auxiliary_lines[j].IsLeftFrame)
 82                     {
 83                         auxiliary_lines[j].PaintValue = ControlHelper.ComputePaintLocationY(value_max_left, value_min_left, height - upDowm - upDowm, auxiliary_lines[j].Value) + (float)upDowm;
 84                     }
 85                     else
 86                     {
 87                         auxiliary_lines[j].PaintValue = ControlHelper.ComputePaintLocationY(value_max_right, value_min_right, height - upDowm - upDowm, auxiliary_lines[j].Value) + (float)upDowm;
 88                     }
 89                 }
 90                 for (int k = 0; k <= value_Segment; k++)
 91                 {
 92                     float value = (float)((double)k * (double)(value_max_left - value_min_left) / (double)value_Segment + (double)value_min_left);
 93                     float num4 = ControlHelper.ComputePaintLocationY(value_max_left, value_min_left, height - upDowm - upDowm, value) + (float)upDowm;
 94                     if (IsNeedPaintDash(num4))
 95                     {
 96                         graphics.DrawLine(pen_normal, leftRight - 4, num4, leftRight - 1, num4);
 97                         RectangleF layoutRectangle = new RectangleF(0f, num4 - 9f, leftRight - 4, 20f);
 98                         graphics.DrawString(value.ToString(), font_size9, brush_deep, layoutRectangle, format_right);
 99                         if (isRenderRightCoordinate)
100                         {
101                             float num5 = (float)k * (value_max_right - value_min_right) / (float)value_Segment + value_min_right;
102                             graphics.DrawLine(pen_normal, width - leftRight + 1, num4, width - leftRight + 4, num4);
103                             layoutRectangle.Location = new PointF(width - leftRight + 4, num4 - 9f);
104                             graphics.DrawString(num5.ToString(), font_size9, brush_deep, layoutRectangle, format_left);
105                         }
106                         if (k > 0 && value_IsRenderDashLine)
107                         {
108                             graphics.DrawLine(pen_dash, leftRight, num4, width - leftRight, num4);
109                         }
110                     }
111                 }
112                 if (value_IsRenderDashLine)
113                 {
114                     if (value_IsAbscissaStrech)
115                     {
116                         float num6 = (float)(width - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
117                         int num7 = CalculateDataCountByOffect(num6);
118                         for (int l = 0; l < value_StrechDataCountMax; l += num7)
119                         {
120                             if (l > 0 && l < value_StrechDataCountMax - 1)
121                             {
122                                 graphics.DrawLine(pen_dash, (float)l * num6 + (float)leftRight, upDowm, (float)l * num6 + (float)leftRight, height - upDowm - 1);
123                             }
124                             if (data_text != null && l < data_text.Length && (float)l * num6 + (float)leftRight < (float)(data_text.Length - 1) * num6 + (float)leftRight - 40f)
125                             {
126                                 graphics.DrawString(layoutRectangle: new Rectangle((int)((float)l * num6), height - upDowm + 1, leftRight * 2, upDowm), s: data_text[l], font: font_size9, brush: brush_deep, format: format_center);
127                             }
128                         }
129                         string[] array2 = data_text;
130                         if (array2 != null && array2.Length > 1)
131                         {
132                             if (data_text.Length < value_StrechDataCountMax)
133                             {
134                                 graphics.DrawLine(pen_dash, (float)(data_text.Length - 1) * num6 + (float)leftRight, upDowm, (float)(data_text.Length - 1) * num6 + (float)leftRight, height - upDowm - 1);
135                             }
136                             graphics.DrawString(layoutRectangle: new Rectangle((int)((float)(data_text.Length - 1) * num6 + (float)leftRight) - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
137                         }
138                     }
139                     else if (value_IntervalAbscissaText > 0)
140                     {
141                         int num8 = width - 2 * leftRight + 1;
142                         for (int m = leftRight; m < width - leftRight; m += value_IntervalAbscissaText)
143                         {
144                             if (m != leftRight)
145                             {
146                                 graphics.DrawLine(pen_dash, m, upDowm, m, height - upDowm - 1);
147                             }
148                             if (data_text == null)
149                             {
150                                 continue;
151                             }
152                             int num9 = (num8 > data_text.Length) ? data_text.Length : num8;
153                             if (m - leftRight < data_text.Length && num9 - (m - leftRight) > 40)
154                             {
155                                 if (data_text.Length <= num8)
156                                 {
157                                     graphics.DrawString(layoutRectangle: new Rectangle(m - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[m - leftRight], font: font_size9, brush: brush_deep, format: format_center);
158                                 }
159                                 else
160                                 {
161                                     graphics.DrawString(layoutRectangle: new Rectangle(m - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[m - leftRight + data_text.Length - num8], font: font_size9, brush: brush_deep, format: format_center);
162                                 }
163                             }
164                         }
165                         string[] array3 = data_text;
166                         if (array3 != null && array3.Length > 1)
167                         {
168                             if (data_text.Length >= num8)
169                             {
170                                 graphics.DrawString(layoutRectangle: new Rectangle(width - leftRight - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
171                             }
172                             else
173                             {
174                                 graphics.DrawLine(pen_dash, data_text.Length + leftRight - 1, upDowm, data_text.Length + leftRight - 1, height - upDowm - 1);
175                                 graphics.DrawString(layoutRectangle: new Rectangle(data_text.Length + leftRight - 1 - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
176                             }
177                         }
178                     }
179                 }
180                 for (int n = 0; n < auxiliary_lines.Count; n++)
181                 {
182                     if (auxiliary_lines[n].IsLeftFrame)
183                     {
184                         graphics.DrawLine(auxiliary_lines[n].GetPen(), leftRight - 4, auxiliary_lines[n].PaintValue, leftRight - 1, auxiliary_lines[n].PaintValue);
185                         graphics.DrawString(layoutRectangle: new RectangleF(0f, auxiliary_lines[n].PaintValue - 9f, leftRight - 4, 20f), s: auxiliary_lines[n].Value.ToString(), font: font_size9, brush: auxiliary_lines[n].LineTextBrush, format: format_right);
186                     }
187                     else
188                     {
189                         graphics.DrawLine(auxiliary_lines[n].GetPen(), width - leftRight + 1, auxiliary_lines[n].PaintValue, width - leftRight + 4, auxiliary_lines[n].PaintValue);
190                         graphics.DrawString(layoutRectangle: new RectangleF(width - leftRight + 4, auxiliary_lines[n].PaintValue - 9f, leftRight - 4, 20f), s: auxiliary_lines[n].Value.ToString(), font: font_size9, brush: auxiliary_lines[n].LineTextBrush, format: format_left);
191                     }
192                     graphics.DrawLine(auxiliary_lines[n].GetPen(), leftRight, auxiliary_lines[n].PaintValue, width - leftRight, auxiliary_lines[n].PaintValue);
193                 }
194                 if (value_IsAbscissaStrech)
195                 {
196                     foreach (MarkText MarkText in MarkTexts)
197                     {
198                         foreach (KeyValuePair<string, CurveItem> item2 in data_list)
199                         {
200                             if (item2.Value.Visible && item2.Value.LineRenderVisiable && !(item2.Key != MarkText.CurveKey))
201                             {
202                                 float[] data = item2.Value.Data;
203                                 if (data != null && data.Length > 1)
204                                 {
205                                     float num10 = (float)(width - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
206                                     if (MarkText.Index >= 0 && MarkText.Index < item2.Value.Data.Length)
207                                     {
208                                         PointF pointF = new PointF((float)leftRight + (float)MarkText.Index * num10, ControlHelper.ComputePaintLocationY(item2.Value.IsLeftFrame ? value_max_left : value_max_right, item2.Value.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, item2.Value.Data[MarkText.Index]) + (float)upDowm);
209                                         graphics.FillEllipse(new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 3f, pointF.Y - 3f, 6f, 6f));
210                                         switch ((MarkText.PositionStyle == MarkTextPositionStyle.Auto) ? MarkText.CalculateDirectionFromDataIndex(item2.Value.Data, MarkText.Index) : MarkText.PositionStyle)
211                                         {
212                                             case MarkTextPositionStyle.Left:
213                                                 graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 100f, pointF.Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
214                                                 break;
215                                             case MarkTextPositionStyle.Up:
216                                                 graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 100f, pointF.Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
217                                                 break;
218                                             case MarkTextPositionStyle.Right:
219                                                 graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X + (float)MarkText.MarkTextOffect, pointF.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
220                                                 break;
221                                             case MarkTextPositionStyle.Down:
222                                                 graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 100f, pointF.Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
223                                                 break;
224                                         }
225                                     }
226                                 }
227                             }
228                         }
229                     }
230                     foreach (CurveItem value2 in data_list.Values)
231                     {
232                         if (value2.Visible && value2.LineRenderVisiable)
233                         {
234                             float[] data2 = value2.Data;
235                             if (data2 != null && data2.Length > 1)
236                             {
237                                 float num11 = (float)(width - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
238                                 PointF[] array4 = new PointF[value2.Data.Length];
239                                 for (int num12 = 0; num12 < value2.Data.Length; num12++)
240                                 {
241                                     array4[num12].X = (float)leftRight + (float)num12 * num11;
242                                     array4[num12].Y = ControlHelper.ComputePaintLocationY(value2.IsLeftFrame ? value_max_left : value_max_right, value2.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, value2.Data[num12]) + (float)upDowm;
243                                     if (!string.IsNullOrEmpty(value2.MarkText[num12]))
244                                     {
245                                         using (Brush brush = new SolidBrush(value2.LineColor))
246                                         {
247                                             graphics.FillEllipse(brush, new RectangleF(array4[num12].X - 3f, array4[num12].Y - 3f, 6f, 6f));
248                                             switch (MarkText.CalculateDirectionFromDataIndex(value2.Data, num12))
249                                             {
250                                                 case MarkTextPositionStyle.Left:
251                                                     graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X - 100f, array4[num12].Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
252                                                     break;
253                                                 case MarkTextPositionStyle.Up:
254                                                     graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X - 100f, array4[num12].Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
255                                                     break;
256                                                 case MarkTextPositionStyle.Right:
257                                                     graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X + (float)MarkText.MarkTextOffect, array4[num12].Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
258                                                     break;
259                                                 case MarkTextPositionStyle.Down:
260                                                     graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X - 100f, array4[num12].Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
261                                                     break;
262                                             }
263                                         }
264                                     }
265                                 }
266                                 using (Pen pen2 = new Pen(value2.LineColor, value2.LineThickness))
267                                 {
268                                     if (value2.IsSmoothCurve)
269                                     {
270                                         graphics.DrawCurve(pen2, array4);
271                                     }
272                                     else
273                                     {
274                                         graphics.DrawLines(pen2, array4);
275                                     }
276                                 }
277                             }
278                         }
279                     }
280                 }
281                 else
282                 {
283                     foreach (MarkText MarkText2 in MarkTexts)
284                     {
285                         foreach (KeyValuePair<string, CurveItem> item3 in data_list)
286                         {
287                             if (item3.Value.Visible && item3.Value.LineRenderVisiable && !(item3.Key != MarkText2.CurveKey))
288                             {
289                                 float[] data3 = item3.Value.Data;
290                                 if (data3 != null && data3.Length > 1 && MarkText2.Index >= 0 && MarkText2.Index < item3.Value.Data.Length)
291                                 {
292                                     PointF pointF2 = new PointF(leftRight + MarkText2.Index, ControlHelper.ComputePaintLocationY(item3.Value.IsLeftFrame ? value_max_left : value_max_right, item3.Value.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, item3.Value.Data[MarkText2.Index]) + (float)upDowm);
293                                     graphics.FillEllipse(new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 3f, pointF2.Y - 3f, 6f, 6f));
294                                     switch ((MarkText2.PositionStyle == MarkTextPositionStyle.Auto) ? MarkText.CalculateDirectionFromDataIndex(item3.Value.Data, MarkText2.Index) : MarkText2.PositionStyle)
295                                     {
296                                         case MarkTextPositionStyle.Left:
297                                             graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 100f, pointF2.Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
298                                             break;
299                                         case MarkTextPositionStyle.Up:
300                                             graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 100f, pointF2.Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
301                                             break;
302                                         case MarkTextPositionStyle.Right:
303                                             graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X + (float)MarkText.MarkTextOffect, pointF2.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
304                                             break;
305                                         case MarkTextPositionStyle.Down:
306                                             graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 100f, pointF2.Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
307                                             break;
308                                     }
309                                 }
310                             }
311                         }
312                     }
313                     foreach (CurveItem value3 in data_list.Values)
314                     {
315                         if (value3.Visible && value3.LineRenderVisiable)
316                         {
317                             float[] data4 = value3.Data;
318                             if (data4 != null && data4.Length > 1)
319                             {
320                                 int num13 = width - 2 * leftRight + 1;
321                                 PointF[] array5;
322                                 if (value3.Data.Length <= num13)
323                                 {
324                                     array5 = new PointF[value3.Data.Length];
325                                     for (int num14 = 0; num14 < value3.Data.Length; num14++)
326                                     {
327                                         array5[num14].X = leftRight + num14;
328                                         array5[num14].Y = ControlHelper.ComputePaintLocationY(value3.IsLeftFrame ? value_max_left : value_max_right, value3.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, value3.Data[num14]) + (float)upDowm;
329                                         DrawMarkPoint(graphics, value3.MarkText[num14], array5[num14], value3.LineColor, MarkText.CalculateDirectionFromDataIndex(value3.Data, num14));
330                                     }
331                                 }
332                                 else
333                                 {
334                                     array5 = new PointF[num13];
335                                     for (int num15 = 0; num15 < array5.Length; num15++)
336                                     {
337                                         int num16 = num15 + value3.Data.Length - num13;
338                                         array5[num15].X = leftRight + num15;
339                                         array5[num15].Y = ControlHelper.ComputePaintLocationY(value3.IsLeftFrame ? value_max_left : value_max_right, value3.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, value3.Data[num16]) + (float)upDowm;
340                                         DrawMarkPoint(graphics, value3.MarkText[num16], array5[num15], value3.LineColor, MarkText.CalculateDirectionFromDataIndex(value3.Data, num16));
341                                     }
342                                 }
343                                 using (Pen pen3 = new Pen(value3.LineColor, value3.LineThickness))
344                                 {
345                                     if (value3.IsSmoothCurve)
346                                     {
347                                         graphics.DrawCurve(pen3, array5);
348                                     }
349                                     else
350                                     {
351                                         graphics.DrawLines(pen3, array5);
352                                     }
353                                 }
354                             }
355                         }
356                     }
357                 }
358                 base.OnPaint(e);
359             }
360             catch (Exception exc)
361             {
362                 e.Graphics.DrawString(exc.Message, this.Font, Brushes.Black, 10, 10);
363             }
364         }

复制代码

辅助函数

复制代码

 1  /// <summary>
 2         /// Draws the mark point.
 3         /// </summary>
 4         /// <param name="g">The g.</param>
 5         /// <param name="markText">The mark text.</param>
 6         /// <param name="center">The center.</param>
 7         /// <param name="color">The color.</param>
 8         /// <param name="markTextPosition">The mark text position.</param>
 9         private void DrawMarkPoint(Graphics g, string markText, PointF center, Color color, MarkTextPositionStyle markTextPosition)
10         {
11             if (!string.IsNullOrEmpty(markText))
12             {
13                 using (Brush brush = new SolidBrush(color))
14                 {
15                     DrawMarkPoint(g, markText, center, brush, markTextPosition);
16                 }
17             }
18         }
19 
20         /// <summary>
21         /// Draws the mark point.
22         /// </summary>
23         /// <param name="g">The g.</param>
24         /// <param name="markText">The mark text.</param>
25         /// <param name="center">The center.</param>
26         /// <param name="brush">The brush.</param>
27         /// <param name="markTextPosition">The mark text position.</param>
28         private void DrawMarkPoint(Graphics g, string markText, PointF center, Brush brush, MarkTextPositionStyle markTextPosition)
29         {
30             if (!string.IsNullOrEmpty(markText))
31             {
32                 g.FillEllipse(brush, new RectangleF(center.X - 3f, center.Y - 3f, 6f, 6f));
33                 switch (markTextPosition)
34                 {
35                     case MarkTextPositionStyle.Left:
36                         g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
37                         break;
38                     case MarkTextPositionStyle.Up:
39                         g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
40                         break;
41                     case MarkTextPositionStyle.Right:
42                         g.DrawString(markText, Font, brush, new RectangleF(center.X + (float)MarkText.MarkTextOffect, center.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
43                         break;
44                     case MarkTextPositionStyle.Down:
45                         g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
46                         break;
47                 }
48             }
49         }
50 
51         /// <summary>
52         /// Determines whether [is need paint dash] [the specified paint value].
53         /// </summary>
54         /// <param name="paintValue">The paint value.</param>
55         /// <returns><c>true</c> if [is need paint dash] [the specified paint value]; otherwise, <c>false</c>.</returns>
56         private bool IsNeedPaintDash(float paintValue)
57         {
58             for (int i = 0; i < auxiliary_lines.Count; i++)
59             {
60                 if (Math.Abs(auxiliary_lines[i].PaintValue - paintValue) < (float)font_size9.Height)
61                 {
62                     return false;
63                 }
64             }
65             return true;
66         }
67 
68         /// <summary>
69         /// Calculates the data count by offect.
70         /// </summary>
71         /// <param name="offect">The offect.</param>
72         /// <returns>System.Int32.</returns>
73         private int CalculateDataCountByOffect(float offect)
74         {
75             if (value_IntervalAbscissaText > 0)
76             {
77                 return value_IntervalAbscissaText;
78             }
79             if (offect > 40f)
80             {
81                 return 1;
82             }
83             offect = 40f / offect;
84             return (int)Math.Ceiling(offect);
85         }

复制代码

一些公开函数

复制代码

  1  /// <summary>
  2         /// Sets the curve text.
  3         /// </summary>
  4         /// <param name="descriptions">The descriptions.</param>
  5         public void SetCurveText(string[] descriptions)
  6         {
  7             data_text = descriptions;
  8             Invalidate();
  9         }
 10 
 11         /// <summary>
 12         /// Sets the left curve.
 13         /// </summary>
 14         /// <param name="key">The key.</param>
 15         /// <param name="data">The data.</param>
 16         /// <param name="lineColor">Color of the line.</param>
 17         public void SetLeftCurve(string key, float[] data, Color? lineColor = null)
 18         {
 19             SetCurve(key, true, data, lineColor, 1f, false);
 20         }
 21 
 22         /// <summary>
 23         /// Sets the left curve.
 24         /// </summary>
 25         /// <param name="key">The key.</param>
 26         /// <param name="data">The data.</param>
 27         /// <param name="lineColor">Color of the line.</param>
 28         /// <param name="isSmooth">if set to <c>true</c> [is smooth].</param>
 29         public void SetLeftCurve(string key, float[] data, Color? lineColor, bool isSmooth = false)
 30         {
 31             SetCurve(key, true, data, lineColor, 1f, isSmooth);
 32         }
 33 
 34         /// <summary>
 35         /// Sets the right curve.
 36         /// </summary>
 37         /// <param name="key">The key.</param>
 38         /// <param name="data">The data.</param>
 39         /// <param name="lineColor">Color of the line.</param>
 40         public void SetRightCurve(string key, float[] data, Color? lineColor = null)
 41         {
 42             SetCurve(key, false, data, lineColor, 1f, false);
 43         }
 44 
 45         /// <summary>
 46         /// Sets the right curve.
 47         /// </summary>
 48         /// <param name="key">The key.</param>
 49         /// <param name="data">The data.</param>
 50         /// <param name="lineColor">Color of the line.</param>
 51         /// <param name="isSmooth">if set to <c>true</c> [is smooth].</param>
 52         public void SetRightCurve(string key, float[] data, Color? lineColor, bool isSmooth = false)
 53         {
 54             SetCurve(key, false, data, lineColor, 1f, isSmooth);
 55         }
 56 
 57         /// <summary>
 58         /// Sets the curve.
 59         /// </summary>
 60         /// <param name="key">The key.</param>
 61         /// <param name="isLeft">if set to <c>true</c> [is left].</param>
 62         /// <param name="data">The data.</param>
 63         /// <param name="lineColor">Color of the line.</param>
 64         /// <param name="thickness">The thickness.</param>
 65         /// <param name="isSmooth">if set to <c>true</c> [is smooth].</param>
 66         public void SetCurve(string key, bool isLeft, float[] data, Color? lineColor, float thickness, bool isSmooth)
 67         {
 68             if (data_list.ContainsKey(key))
 69             {
 70                 if (data == null)
 71                 {
 72                     data = new float[0];
 73                 }
 74                 data_list[key].Data = data;
 75             }
 76             else
 77             {
 78                 if (data == null)
 79                 {
 80                     data = new float[0];
 81                 }
 82                 data_list.Add(key, new CurveItem
 83                 {
 84                     Data = data,
 85                     MarkText = new string[data.Length],
 86                     LineThickness = thickness,
 87                     LineColor = lineColor ?? ControlHelper.Colors[data_list.Count + 13],
 88                     IsLeftFrame = isLeft,
 89                     IsSmoothCurve = isSmooth
 90                 });
 91                 if (data_text == null)
 92                 {
 93                     data_text = new string[data.Length];
 94                 }
 95             }
 96             Invalidate();
 97         }
 98 
 99         /// <summary>
100         /// Removes the curve.
101         /// </summary>
102         /// <param name="key">The key.</param>
103         public void RemoveCurve(string key)
104         {
105             if (data_list.ContainsKey(key))
106             {
107                 data_list.Remove(key);
108             }
109             if (data_list.Count == 0)
110             {
111                 data_text = new string[0];
112             }
113             Invalidate();
114         }
115 
116         /// <summary>
117         /// Removes all curve.
118         /// </summary>
119         public void RemoveAllCurve()
120         {
121             int count = data_list.Count;
122             data_list.Clear();
123             if (data_list.Count == 0)
124             {
125                 data_text = new string[0];
126             }
127             if (count > 0)
128             {
129                 Invalidate();
130             }
131         }
132 
133         /// <summary>
134         /// Removes all curve data.
135         /// </summary>
136         public void RemoveAllCurveData()
137         {
138             int count = data_list.Count;
139             foreach (KeyValuePair<string, CurveItem> item in data_list)
140             {
141                 item.Value.Data = new float[0];
142                 item.Value.MarkText = new string[0];
143             }
144             data_text = new string[0];
145             if (count > 0)
146             {
147                 Invalidate();
148             }
149         }
150 
151         /// <summary>
152         /// Gets the curve item.
153         /// </summary>
154         /// <param name="key">The key.</param>
155         /// <returns>CurveItem.</returns>
156         public CurveItem GetCurveItem(string key)
157         {
158             if (data_list.ContainsKey(key))
159             {
160                 return data_list[key];
161             }
162             return null;
163         }
164 
165         /// <summary>
166         /// Saves to bitmap.
167         /// </summary>
168         /// <returns>Bitmap.</returns>
169         public Bitmap SaveToBitmap()
170         {
171             return SaveToBitmap(base.Width, base.Height);
172         }
173 
174         /// <summary>
175         /// Saves to bitmap.
176         /// </summary>
177         /// <param name="width">The width.</param>
178         /// <param name="height">The height.</param>
179         /// <returns>Bitmap.</returns>
180         public Bitmap SaveToBitmap(int width, int height)
181         {
182             Bitmap bitmap = new Bitmap(width, height);
183             Graphics graphics = Graphics.FromImage(bitmap);
184             OnPaint(new PaintEventArgs(graphics, new Rectangle(0, 0, width, height)));
185             return bitmap;
186         }
187 
188         /// <summary>
189         /// Adds the curve data.
190         /// </summary>
191         /// <param name="key">The key.</param>
192         /// <param name="values">The values.</param>
193         /// <param name="markTexts">The mark texts.</param>
194         /// <param name="isUpdateUI">if set to <c>true</c> [is update UI].</param>
195         private void AddCurveData(string key, float[] values, string[] markTexts, bool isUpdateUI)
196         {
197             if ((values != null && values.Length < 1) || !data_list.ContainsKey(key))
198             {
199                 return;
200             }
201             CurveItem CurveItem = data_list[key];
202             if (CurveItem.Data != null)
203             {
204                 if (value_IsAbscissaStrech)
205                 {
206                     ControlHelper.AddArrayData(ref CurveItem.Data, values, value_StrechDataCountMax);
207                     ControlHelper.AddArrayData(ref CurveItem.MarkText, markTexts, value_StrechDataCountMax);
208                 }
209                 else
210                 {
211                     ControlHelper.AddArrayData(ref CurveItem.Data, values, 4096);
212                     ControlHelper.AddArrayData(ref CurveItem.MarkText, markTexts, 4096);
213                 }
214                 if (isUpdateUI)
215                 {
216                     Invalidate();
217                 }
218             }
219         }
220 
221         /// <summary>
222         /// Adds the curve time.
223         /// </summary>
224         /// <param name="count">The count.</param>
225         private void AddCurveTime(int count)
226         {
227             AddCurveTime(count, DateTime.Now.ToString(textFormat));
228         }
229 
230         /// <summary>
231         /// Adds the curve time.
232         /// </summary>
233         /// <param name="count">The count.</param>
234         /// <param name="text">The text.</param>
235         private void AddCurveTime(int count, string text)
236         {
237             if (data_text != null)
238             {
239                 string[] array = new string[count];
240                 for (int i = 0; i < array.Length; i++)
241                 {
242                     array[i] = text;
243                 }
244                 if (value_IsAbscissaStrech)
245                 {
246                     ControlHelper.AddArrayData(ref data_text, array, value_StrechDataCountMax);
247                 }
248                 else
249                 {
250                     ControlHelper.AddArrayData(ref data_text, array, 4096);
251                 }
252             }
253         }
254 
255         /// <summary>
256         /// Adds the curve data.
257         /// </summary>
258         /// <param name="key">The key.</param>
259         /// <param name="value">The value.</param>
260         public void AddCurveData(string key, float value)
261         {
262             AddCurveData(key, new float[1]
263             {
264                 value
265             });
266         }
267 
268         /// <summary>
269         /// Adds the curve data.
270         /// </summary>
271         /// <param name="key">The key.</param>
272         /// <param name="value">The value.</param>
273         /// <param name="markText">The mark text.</param>
274         public void AddCurveData(string key, float value, string markText)
275         {
276             AddCurveData(key, new float[1]
277             {
278                 value
279             }, new string[1]
280             {
281                 markText
282             });
283         }
284 
285         /// <summary>
286         /// Adds the curve data.
287         /// </summary>
288         /// <param name="key">The key.</param>
289         /// <param name="values">The values.</param>
290         public void AddCurveData(string key, float[] values)
291         {
292             AddCurveData(key, values, null);
293         }
294 
295         /// <summary>
296         /// Adds the curve data.
297         /// </summary>
298         /// <param name="key">The key.</param>
299         /// <param name="values">The values.</param>
300         /// <param name="markTexts">The mark texts.</param>
301         public void AddCurveData(string key, float[] values, string[] markTexts)
302         {
303             if (markTexts == null)
304             {
305                 markTexts = new string[values.Length];
306             }
307             AddCurveData(key, values, markTexts, false);
308             if (values != null && values.Length != 0)
309             {
310                 AddCurveTime(values.Length);
311             }
312             Invalidate();
313         }
314 
315         /// <summary>
316         /// Adds the curve data.
317         /// </summary>
318         /// <param name="keys">The keys.</param>
319         /// <param name="values">The values.</param>
320         public void AddCurveData(string[] keys, float[] values)
321         {
322             AddCurveData(keys, values, null);
323         }
324 
325         /// <summary>
326         /// Adds the curve data.
327         /// </summary>
328         /// <param name="axisText">The axis text.</param>
329         /// <param name="keys">The keys.</param>
330         /// <param name="values">The values.</param>
331         public void AddCurveData(string axisText, string[] keys, float[] values)
332         {
333             AddCurveData(axisText, keys, values, null);
334         }
335 
336         /// <summary>
337         /// Adds the curve data.
338         /// </summary>
339         /// <param name="keys">The keys.</param>
340         /// <param name="values">The values.</param>
341         /// <param name="markTexts">The mark texts.</param>
342         /// <exception cref="ArgumentNullException">keys
343         /// or
344         /// values</exception>
345         /// <exception cref="Exception">两个参数的数组长度不一致。
346         /// or
347         /// 两个参数的数组长度不一致。</exception>
348         public void AddCurveData(string[] keys, float[] values, string[] markTexts)
349         {
350             if (keys == null)
351             {
352                 throw new ArgumentNullException("keys");
353             }
354             if (values == null)
355             {
356                 throw new ArgumentNullException("values");
357             }
358             if (markTexts == null)
359             {
360                 markTexts = new string[keys.Length];
361             }
362             if (keys.Length != values.Length)
363             {
364                 throw new Exception("两个参数的数组长度不一致。");
365             }
366             if (keys.Length != markTexts.Length)
367             {
368                 throw new Exception("两个参数的数组长度不一致。");
369             }
370             for (int i = 0; i < keys.Length; i++)
371             {
372                 AddCurveData(keys[i], new float[1]
373                 {
374                     values[i]
375                 }, new string[1]
376                 {
377                     markTexts[i]
378                 }, false);
379             }
380             AddCurveTime(1);
381             Invalidate();
382         }
383 
384         /// <summary>
385         /// Adds the curve data.
386         /// </summary>
387         /// <param name="axisText">The axis text.</param>
388         /// <param name="keys">The keys.</param>
389         /// <param name="values">The values.</param>
390         /// <param name="markTexts">The mark texts.</param>
391         /// <exception cref="ArgumentNullException">keys
392         /// or
393         /// values</exception>
394         /// <exception cref="Exception">两个参数的数组长度不一致。
395         /// or
396         /// 两个参数的数组长度不一致。</exception>
397         public void AddCurveData(string axisText, string[] keys, float[] values, string[] markTexts)
398         {
399             if (keys == null)
400             {
401                 throw new ArgumentNullException("keys");
402             }
403             if (values == null)
404             {
405                 throw new ArgumentNullException("values");
406             }
407             if (markTexts == null)
408             {
409                 markTexts = new string[keys.Length];
410             }
411             if (keys.Length != values.Length)
412             {
413                 throw new Exception("两个参数的数组长度不一致。");
414             }
415             if (keys.Length != markTexts.Length)
416             {
417                 throw new Exception("两个参数的数组长度不一致。");
418             }
419             for (int i = 0; i < keys.Length; i++)
420             {
421                 AddCurveData(keys[i], new float[1]
422                 {
423                     values[i]
424                 }, new string[1]
425                 {
426                     markTexts[i]
427                 }, false);
428             }
429             AddCurveTime(1, axisText);
430             Invalidate();
431         }
432 
433         /// <summary>
434         /// Sets the curve visible.
435         /// </summary>
436         /// <param name="key">The key.</param>
437         /// <param name="visible">if set to <c>true</c> [visible].</param>
438         public void SetCurveVisible(string key, bool visible)
439         {
440             if (data_list.ContainsKey(key))
441             {
442                 CurveItem CurveItem = data_list[key];
443                 CurveItem.Visible = visible;
444                 Invalidate();
445             }
446         }
447 
448         /// <summary>
449         /// Sets the curve visible.
450         /// </summary>
451         /// <param name="keys">The keys.</param>
452         /// <param name="visible">if set to <c>true</c> [visible].</param>
453         public void SetCurveVisible(string[] keys, bool visible)
454         {
455             foreach (string key in keys)
456             {
457                 if (data_list.ContainsKey(key))
458                 {
459                     CurveItem CurveItem = data_list[key];
460                     CurveItem.Visible = visible;
461                 }
462             }
463             Invalidate();
464         }
465 
466         /// <summary>
467         /// Adds the left auxiliary.
468         /// </summary>
469         /// <param name="value">The value.</param>
470         public void AddLeftAuxiliary(float value)
471         {
472             AddLeftAuxiliary(value, ColorLinesAndText);
473         }
474 
475         /// <summary>
476         /// Adds the left auxiliary.
477         /// </summary>
478         /// <param name="value">The value.</param>
479         /// <param name="lineColor">Color of the line.</param>
480         public void AddLeftAuxiliary(float value, Color lineColor)
481         {
482             AddLeftAuxiliary(value, lineColor, 1f, true);
483         }
484 
485         /// <summary>
486         /// Adds the left auxiliary.
487         /// </summary>
488         /// <param name="value">The value.</param>
489         /// <param name="lineColor">Color of the line.</param>
490         /// <param name="lineThickness">The line thickness.</param>
491         /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
492         public void AddLeftAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine)
493         {
494             AddAuxiliary(value, lineColor, lineThickness, isDashLine, true);
495         }
496 
497         /// <summary>
498         /// Adds the right auxiliary.
499         /// </summary>
500         /// <param name="value">The value.</param>
501         public void AddRightAuxiliary(float value)
502         {
503             AddRightAuxiliary(value, ColorLinesAndText);
504         }
505 
506         /// <summary>
507         /// Adds the right auxiliary.
508         /// </summary>
509         /// <param name="value">The value.</param>
510         /// <param name="lineColor">Color of the line.</param>
511         public void AddRightAuxiliary(float value, Color lineColor)
512         {
513             AddRightAuxiliary(value, lineColor, 1f, true);
514         }
515 
516         /// <summary>
517         /// Adds the right auxiliary.
518         /// </summary>
519         /// <param name="value">The value.</param>
520         /// <param name="lineColor">Color of the line.</param>
521         /// <param name="lineThickness">The line thickness.</param>
522         /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
523         public void AddRightAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine)
524         {
525             AddAuxiliary(value, lineColor, lineThickness, isDashLine, false);
526         }
527 
528         /// <summary>
529         /// Adds the auxiliary.
530         /// </summary>
531         /// <param name="value">The value.</param>
532         /// <param name="lineColor">Color of the line.</param>
533         /// <param name="lineThickness">The line thickness.</param>
534         /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
535         /// <param name="isLeft">if set to <c>true</c> [is left].</param>
536         private void AddAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine, bool isLeft)
537         {
538             auxiliary_lines.Add(new AuxiliaryLine
539             {
540                 Value = value,
541                 LineColor = lineColor,
542                 PenDash = new Pen(lineColor)
543                 {
544                     DashStyle = DashStyle.Custom,
545                     DashPattern = new float[2]
546                     {
547                         5f,
548                         5f
549                     }
550                 },
551                 PenSolid = new Pen(lineColor),
552                 IsDashStyle = isDashLine,
553                 IsLeftFrame = isLeft,
554                 LineThickness = lineThickness,
555                 LineTextBrush = new SolidBrush(lineColor)
556             });
557             Invalidate();
558         }
559 
560         /// <summary>
561         /// Removes the auxiliary.
562         /// </summary>
563         /// <param name="value">The value.</param>
564         public void RemoveAuxiliary(float value)
565         {
566             int num = 0;
567             for (int num2 = auxiliary_lines.Count - 1; num2 >= 0; num2--)
568             {
569                 if (auxiliary_lines[num2].Value == value)
570                 {
571                     auxiliary_lines[num2].Dispose();
572                     auxiliary_lines.RemoveAt(num2);
573                     num++;
574                 }
575             }
576             if (num > 0)
577             {
578                 Invalidate();
579             }
580         }
581 
582         /// <summary>
583         /// Removes all auxiliary.
584         /// </summary>
585         public void RemoveAllAuxiliary()
586         {
587             int count = auxiliary_lines.Count;
588             auxiliary_lines.Clear();
589             if (count > 0)
590             {
591                 Invalidate();
592             }
593         }
594 
595         /// <summary>
596         /// Adds the auxiliary label.
597         /// </summary>
598         /// <param name="auxiliaryLable">The auxiliary lable.</param>
599         public void AddAuxiliaryLabel(AuxiliaryLable auxiliaryLable)
600         {
601             auxiliary_Labels.Add(auxiliaryLable);
602         }
603 
604         /// <summary>
605         /// Removes the auxiliary lable.
606         /// </summary>
607         /// <param name="auxiliaryLable">The auxiliary lable.</param>
608         public void RemoveAuxiliaryLable(AuxiliaryLable auxiliaryLable)
609         {
610             if (auxiliary_Labels.Remove(auxiliaryLable))
611             {
612                 Invalidate();
613             }
614         }
615 
616         /// <summary>
617         /// Removes all auxiliary lable.
618         /// </summary>
619         public void RemoveAllAuxiliaryLable()
620         {
621             int count = auxiliary_Labels.Count;
622             auxiliary_Labels.Clear();
623             if (count > 0)
624             {
625                 Invalidate();
626             }
627         }
628 
629         /// <summary>
630         /// Adds the mark text.
631         /// </summary>
632         /// <param name="markText">The mark text.</param>
633         public void AddMarkText(MarkText markText)
634         {
635             MarkTexts.Add(markText);
636             if (data_list.Count > 0)
637             {
638                 Invalidate();
639             }
640         }
641 
642         /// <summary>
643         /// Adds the mark text.
644         /// </summary>
645         /// <param name="strCurveKey">The string curve key.</param>
646         /// <param name="intValueIndex">Index of the int value.</param>
647         /// <param name="strText">The string text.</param>
648         /// <param name="textColor">Color of the text.</param>
649         public void AddMarkText(string strCurveKey, int intValueIndex, string strText, Color? textColor = null)
650         {
651             AddMarkText(new MarkText() { CurveKey = strCurveKey, PositionStyle = MarkTextPositionStyle.Auto, Text = strText, TextColor = textColor, Index = intValueIndex });
652         }
653 
654         /// <summary>
655         /// Removes the mark text.
656         /// </summary>
657         /// <param name="markText">The mark text.</param>
658         public void RemoveMarkText(MarkText markText)
659         {
660             MarkTexts.Remove(markText);
661             if (data_list.Count > 0)
662             {
663                 Invalidate();
664             }
665         }
666 
667         /// <summary>
668         /// Removes all mark text.
669         /// </summary>
670         public void RemoveAllMarkText()
671         {
672             MarkTexts.Clear();
673             if (data_list.Count > 0)
674             {
675                 Invalidate();
676             }
677         }

复制代码

其中

MarkText为标注文字相关

AuxiliaryLabel为提示信息相关

Auxiliary为节点信息相关

 

完整代码

// ***********************************************************************
// Assembly         : HZH_Controls
// Created          : 2019-09-23
//
// ***********************************************************************
// <copyright file="UCCurve.cs">
//     Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
// </copyright>
//
// Blog: https://www.cnblogs.com/bfyx
// GitHub:https://github.com/kwwwvagaa/NetWinformControl
// gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// If you use this code, please keep this note.
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows.Forms;

namespace HZH_Controls.Controls
{
    /// <summary>
    /// Class UCCurve.
    /// Implements the <see cref="System.Windows.Forms.UserControl" />
    /// </summary>
    /// <seealso cref="System.Windows.Forms.UserControl" />
    public class UCCurve : UserControl
    {
        /// <summary>
        /// The value count maximum
        /// </summary>
        private const int value_count_max = 4096;

        /// <summary>
        /// The value maximum left
        /// </summary>
        private float value_max_left = 100f;

        /// <summary>
        /// The value minimum left
        /// </summary>
        private float value_min_left = 0f;

        /// <summary>
        /// The value maximum right
        /// </summary>
        private float value_max_right = 100f;

        /// <summary>
        /// The value minimum right
        /// </summary>
        private float value_min_right = 0f;

        /// <summary>
        /// The value segment
        /// </summary>
        private int value_Segment = 5;

        /// <summary>
        /// The value is abscissa strech
        /// </summary>
        private bool value_IsAbscissaStrech = false;

        /// <summary>
        /// The value strech data count maximum
        /// </summary>
        private int value_StrechDataCountMax = 300;

        /// <summary>
        /// The value is render dash line
        /// </summary>
        private bool value_IsRenderDashLine = true;

        /// <summary>
        /// The text format
        /// </summary>
        private string textFormat = "HH:mm";

        /// <summary>
        /// The value interval abscissa text
        /// </summary>
        private int value_IntervalAbscissaText = 100;

        /// <summary>
        /// The random
        /// </summary>
        private Random random = null;

        /// <summary>
        /// The value title
        /// </summary>
        private string value_title = "";

        /// <summary>
        /// The left right
        /// </summary>
        private int leftRight = 50;

        /// <summary>
        /// Up dowm
        /// </summary>
        private int upDowm = 50;

        /// <summary>
        /// The data list
        /// </summary>
        private Dictionary<string, CurveItem> data_list = null;

        /// <summary>
        /// The data text
        /// </summary>
        private string[] data_text = null;

        /// <summary>
        /// The auxiliary lines
        /// </summary>
        private List<AuxiliaryLine> auxiliary_lines;

        /// <summary>
        /// The auxiliary labels
        /// </summary>
        private List<AuxiliaryLable> auxiliary_Labels;

        /// <summary>
        /// The mark texts
        /// </summary>
        private List<MarkText> MarkTexts;

        /// <summary>
        /// The font size9
        /// </summary>
        private Font font_size9 = null;

        /// <summary>
        /// The font size12
        /// </summary>
        private Font font_size12 = null;

        /// <summary>
        /// The brush deep
        /// </summary>
        private Brush brush_deep = null;

        /// <summary>
        /// The pen normal
        /// </summary>
        private Pen pen_normal = null;

        /// <summary>
        /// The pen dash
        /// </summary>
        private Pen pen_dash = null;

        /// <summary>
        /// The color normal
        /// </summary>
        private Color color_normal = Color.DeepPink;

        /// <summary>
        /// The color deep
        /// </summary>
        private Color color_deep = Color.DimGray;

        /// <summary>
        /// The color dash
        /// </summary>
        private Color color_dash = Color.FromArgb(232, 232, 232);

        /// <summary>
        /// The color mark font
        /// </summary>
        private Color color_mark_font = Color.DodgerBlue;

        /// <summary>
        /// The brush mark font
        /// </summary>
        private Brush brush_mark_font = Brushes.DodgerBlue;

        /// <summary>
        /// The format left
        /// </summary>
        private StringFormat format_left = null;

        /// <summary>
        /// The format right
        /// </summary>
        private StringFormat format_right = null;

        /// <summary>
        /// The format center
        /// </summary>
        private StringFormat format_center = null;

        /// <summary>
        /// The is render right coordinate
        /// </summary>
        private bool isRenderRightCoordinate = true;

        /// <summary>
        /// The curve name width
        /// </summary>
        private int curveNameWidth = 100;

        /// <summary>
        /// The components
        /// </summary>
        private IContainer components = null;

        /// <summary>
        /// 获取或设置控件的背景色。
        /// </summary>
        /// <value>The color of the back.</value>
        /// <PermissionSet>
        ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
        /// </PermissionSet>
        [Browsable(true)]
        [Description("获取或设置控件的背景色")]
        [Category("自定义")]
        [DefaultValue(typeof(Color), "Transparent")]
        [EditorBrowsable(EditorBrowsableState.Always)]
        public override Color BackColor
        {
            get
            {
                return base.BackColor;
            }
            set
            {
                base.BackColor = value;
            }
        }

        /// <summary>
        /// Gets or sets the value maximum left.
        /// </summary>
        /// <value>The value maximum left.</value>
        [Category("自定义")]
        [Description("获取或设置图形的左纵坐标的最大值,该值必须大于最小值")]
        [Browsable(true)]
        [DefaultValue(100f)]
        public float ValueMaxLeft
        {
            get
            {
                return value_max_left;
            }
            set
            {
                value_max_left = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the value minimum left.
        /// </summary>
        /// <value>The value minimum left.</value>
        [Category("自定义")]
        [Description("获取或设置图形的左纵坐标的最小值,该值必须小于最大值")]
        [Browsable(true)]
        [DefaultValue(0f)]
        public float ValueMinLeft
        {
            get
            {
                return value_min_left;
            }
            set
            {
                value_min_left = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the value maximum right.
        /// </summary>
        /// <value>The value maximum right.</value>
        [Category("自定义")]
        [Description("获取或设置图形的右纵坐标的最大值,该值必须大于最小值")]
        [Browsable(true)]
        [DefaultValue(100f)]
        public float ValueMaxRight
        {
            get
            {
                return value_max_right;
            }
            set
            {
                value_max_right = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the value minimum right.
        /// </summary>
        /// <value>The value minimum right.</value>
        [Category("自定义")]
        [Description("获取或设置图形的右纵坐标的最小值,该值必须小于最大值")]
        [Browsable(true)]
        [DefaultValue(0f)]
        public float ValueMinRight
        {
            get
            {
                return value_min_right;
            }
            set
            {
                value_min_right = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the value segment.
        /// </summary>
        /// <value>The value segment.</value>
        [Category("自定义")]
        [Description("获取或设置图形的纵轴分段数")]
        [Browsable(true)]
        [DefaultValue(5)]
        public int ValueSegment
        {
            get
            {
                return value_Segment;
            }
            set
            {
                value_Segment = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is abscissa strech.
        /// </summary>
        /// <value><c>true</c> if this instance is abscissa strech; otherwise, <c>false</c>.</value>
        [Category("自定义")]
        [Description("获取或设置所有的数据是否强制在一个界面里显示")]
        [Browsable(true)]
        [DefaultValue(false)]
        public bool IsAbscissaStrech
        {
            get
            {
                return value_IsAbscissaStrech;
            }
            set
            {
                value_IsAbscissaStrech = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the strech data count maximum.
        /// </summary>
        /// <value>The strech data count maximum.</value>
        [Category("自定义")]
        [Description("获取或设置拉伸模式下的最大数据量")]
        [Browsable(true)]
        [DefaultValue(300)]
        public int StrechDataCountMax
        {
            get
            {
                return value_StrechDataCountMax;
            }
            set
            {
                value_StrechDataCountMax = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is render dash line.
        /// </summary>
        /// <value><c>true</c> if this instance is render dash line; otherwise, <c>false</c>.</value>
        [Category("自定义")]
        [Description("获取或设置虚线是否进行显示")]
        [Browsable(true)]
        [DefaultValue(true)]
        public bool IsRenderDashLine
        {
            get
            {
                return value_IsRenderDashLine;
            }
            set
            {
                value_IsRenderDashLine = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the color lines and text.
        /// </summary>
        /// <value>The color lines and text.</value>
        [Category("自定义")]
        [Description("获取或设置坐标轴及相关信息文本的颜色")]
        [Browsable(true)]
        [DefaultValue(typeof(Color), "DimGray")]
        public Color ColorLinesAndText
        {
            get
            {
                return color_deep;
            }
            set
            {
                color_deep = value;
                InitializationColor();
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the color dash lines.
        /// </summary>
        /// <value>The color dash lines.</value>
        [Category("自定义")]
        [Description("获取或设置虚线的颜色")]
        [Browsable(true)]
        public Color ColorDashLines
        {
            get
            {
                return color_dash;
            }
            set
            {
                color_dash = value;
                if (pen_dash != null)
                    pen_dash.Dispose();
                pen_dash = new Pen(color_dash);
                pen_dash.DashStyle = DashStyle.Custom;
                pen_dash.DashPattern = new float[2]
                {
                    5f,
                    5f
                };
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the interval abscissa text.
        /// </summary>
        /// <value>The interval abscissa text.</value>
        [Category("自定义")]
        [Description("获取或设置纵向虚线的分隔情况,单位为多少个数据")]
        [Browsable(true)]
        [DefaultValue(100)]
        public int IntervalAbscissaText
        {
            get
            {
                return value_IntervalAbscissaText;
            }
            set
            {
                value_IntervalAbscissaText = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the text add format.
        /// </summary>
        /// <value>The text add format.</value>
        [Category("自定义")]
        [Description("获取或设置实时数据新增时文本相对应于时间的格式化字符串,默认HH:mm")]
        [Browsable(true)]
        [DefaultValue("HH:mm")]
        public string TextAddFormat
        {
            get
            {
                return textFormat;
            }
            set
            {
                textFormat = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        /// <value>The title.</value>
        [Category("自定义")]
        [Description("获取或设置图标的标题信息")]
        [Browsable(true)]
        [DefaultValue("")]
        public string Title
        {
            get
            {
                return value_title;
            }
            set
            {
                value_title = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance is render right coordinate.
        /// </summary>
        /// <value><c>true</c> if this instance is render right coordinate; otherwise, <c>false</c>.</value>
        [Category("自定义")]
        [Description("获取或设置是否显示右侧的坐标系信息")]
        [Browsable(true)]
        [DefaultValue(true)]
        public bool IsRenderRightCoordinate
        {
            get
            {
                return isRenderRightCoordinate;
            }
            set
            {
                isRenderRightCoordinate = value;
                Invalidate();
            }
        }

        /// <summary>
        /// Gets or sets the width of the curve name.
        /// </summary>
        /// <value>The width of the curve name.</value>
        [Browsable(true)]
        [Description("获取或设置曲线名称的布局宽度")]
        [Category("自定义")]
        [DefaultValue(100)]
        public int CurveNameWidth
        {
            get
            {
                return curveNameWidth;
            }
            set
            {
                if (value > 10)
                {
                    curveNameWidth = value;
                }
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="UCCurve" /> class.
        /// </summary>
        public UCCurve()
        {
            InitializeComponent();
            random = new Random();
            data_list = new Dictionary<string, CurveItem>();
            auxiliary_lines = new List<AuxiliaryLine>();
            MarkTexts = new List<MarkText>();
            auxiliary_Labels = new List<AuxiliaryLable>();
            format_left = new StringFormat
            {
                LineAlignment = StringAlignment.Center,
                Alignment = StringAlignment.Near
            };
            format_right = new StringFormat
            {
                LineAlignment = StringAlignment.Center,
                Alignment = StringAlignment.Far
            };
            format_center = new StringFormat
            {
                LineAlignment = StringAlignment.Center,
                Alignment = StringAlignment.Center
            };
            font_size9 = new Font("微软雅黑", 9f);
            font_size12 = new Font("微软雅黑", 12f);
            InitializationColor();
            pen_dash = new Pen(color_deep);
            pen_dash.DashStyle = DashStyle.Custom;
            pen_dash.DashPattern = new float[2]
            {
                5f,
                5f
            };
            SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        }

        /// <summary>
        /// Initializations the color.
        /// </summary>
        private void InitializationColor()
        {
            if (pen_normal != null)
                pen_normal.Dispose();
            if (brush_deep != null)
                brush_deep.Dispose();
            pen_normal = new Pen(color_deep);
            brush_deep = new SolidBrush(color_deep);
        }

        /// <summary>
        /// Sets the curve text.
        /// </summary>
        /// <param name="descriptions">The descriptions.</param>
        public void SetCurveText(string[] descriptions)
        {
            data_text = descriptions;
            Invalidate();
        }

        /// <summary>
        /// Sets the left curve.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="data">The data.</param>
        /// <param name="lineColor">Color of the line.</param>
        public void SetLeftCurve(string key, float[] data, Color? lineColor = null)
        {
            SetCurve(key, true, data, lineColor, 1f, false);
        }

        /// <summary>
        /// Sets the left curve.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="data">The data.</param>
        /// <param name="lineColor">Color of the line.</param>
        /// <param name="isSmooth">if set to <c>true</c> [is smooth].</param>
        public void SetLeftCurve(string key, float[] data, Color? lineColor, bool isSmooth = false)
        {
            SetCurve(key, true, data, lineColor, 1f, isSmooth);
        }

        /// <summary>
        /// Sets the right curve.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="data">The data.</param>
        /// <param name="lineColor">Color of the line.</param>
        public void SetRightCurve(string key, float[] data, Color? lineColor = null)
        {
            SetCurve(key, false, data, lineColor, 1f, false);
        }

        /// <summary>
        /// Sets the right curve.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="data">The data.</param>
        /// <param name="lineColor">Color of the line.</param>
        /// <param name="isSmooth">if set to <c>true</c> [is smooth].</param>
        public void SetRightCurve(string key, float[] data, Color? lineColor, bool isSmooth = false)
        {
            SetCurve(key, false, data, lineColor, 1f, isSmooth);
        }

        /// <summary>
        /// Sets the curve.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="isLeft">if set to <c>true</c> [is left].</param>
        /// <param name="data">The data.</param>
        /// <param name="lineColor">Color of the line.</param>
        /// <param name="thickness">The thickness.</param>
        /// <param name="isSmooth">if set to <c>true</c> [is smooth].</param>
        public void SetCurve(string key, bool isLeft, float[] data, Color? lineColor, float thickness, bool isSmooth)
        {
            if (data_list.ContainsKey(key))
            {
                if (data == null)
                {
                    data = new float[0];
                }
                data_list[key].Data = data;
            }
            else
            {
                if (data == null)
                {
                    data = new float[0];
                }
                data_list.Add(key, new CurveItem
                {
                    Data = data,
                    MarkText = new string[data.Length],
                    LineThickness = thickness,
                    LineColor = lineColor ?? ControlHelper.Colors[data_list.Count + 13],
                    IsLeftFrame = isLeft,
                    IsSmoothCurve = isSmooth
                });
                if (data_text == null)
                {
                    data_text = new string[data.Length];
                }
            }
            Invalidate();
        }

        /// <summary>
        /// Removes the curve.
        /// </summary>
        /// <param name="key">The key.</param>
        public void RemoveCurve(string key)
        {
            if (data_list.ContainsKey(key))
            {
                data_list.Remove(key);
            }
            if (data_list.Count == 0)
            {
                data_text = new string[0];
            }
            Invalidate();
        }

        /// <summary>
        /// Removes all curve.
        /// </summary>
        public void RemoveAllCurve()
        {
            int count = data_list.Count;
            data_list.Clear();
            if (data_list.Count == 0)
            {
                data_text = new string[0];
            }
            if (count > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Removes all curve data.
        /// </summary>
        public void RemoveAllCurveData()
        {
            int count = data_list.Count;
            foreach (KeyValuePair<string, CurveItem> item in data_list)
            {
                item.Value.Data = new float[0];
                item.Value.MarkText = new string[0];
            }
            data_text = new string[0];
            if (count > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Gets the curve item.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>CurveItem.</returns>
        public CurveItem GetCurveItem(string key)
        {
            if (data_list.ContainsKey(key))
            {
                return data_list[key];
            }
            return null;
        }

        /// <summary>
        /// Saves to bitmap.
        /// </summary>
        /// <returns>Bitmap.</returns>
        public Bitmap SaveToBitmap()
        {
            return SaveToBitmap(base.Width, base.Height);
        }

        /// <summary>
        /// Saves to bitmap.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <returns>Bitmap.</returns>
        public Bitmap SaveToBitmap(int width, int height)
        {
            Bitmap bitmap = new Bitmap(width, height);
            Graphics graphics = Graphics.FromImage(bitmap);
            OnPaint(new PaintEventArgs(graphics, new Rectangle(0, 0, width, height)));
            return bitmap;
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="values">The values.</param>
        /// <param name="markTexts">The mark texts.</param>
        /// <param name="isUpdateUI">if set to <c>true</c> [is update UI].</param>
        private void AddCurveData(string key, float[] values, string[] markTexts, bool isUpdateUI)
        {
            if ((values != null && values.Length < 1) || !data_list.ContainsKey(key))
            {
                return;
            }
            CurveItem CurveItem = data_list[key];
            if (CurveItem.Data != null)
            {
                if (value_IsAbscissaStrech)
                {
                    ControlHelper.AddArrayData(ref CurveItem.Data, values, value_StrechDataCountMax);
                    ControlHelper.AddArrayData(ref CurveItem.MarkText, markTexts, value_StrechDataCountMax);
                }
                else
                {
                    ControlHelper.AddArrayData(ref CurveItem.Data, values, 4096);
                    ControlHelper.AddArrayData(ref CurveItem.MarkText, markTexts, 4096);
                }
                if (isUpdateUI)
                {
                    Invalidate();
                }
            }
        }

        /// <summary>
        /// Adds the curve time.
        /// </summary>
        /// <param name="count">The count.</param>
        private void AddCurveTime(int count)
        {
            AddCurveTime(count, DateTime.Now.ToString(textFormat));
        }

        /// <summary>
        /// Adds the curve time.
        /// </summary>
        /// <param name="count">The count.</param>
        /// <param name="text">The text.</param>
        private void AddCurveTime(int count, string text)
        {
            if (data_text != null)
            {
                string[] array = new string[count];
                for (int i = 0; i < array.Length; i++)
                {
                    array[i] = text;
                }
                if (value_IsAbscissaStrech)
                {
                    ControlHelper.AddArrayData(ref data_text, array, value_StrechDataCountMax);
                }
                else
                {
                    ControlHelper.AddArrayData(ref data_text, array, 4096);
                }
            }
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        public void AddCurveData(string key, float value)
        {
            AddCurveData(key, new float[1]
            {
                value
            });
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        /// <param name="markText">The mark text.</param>
        public void AddCurveData(string key, float value, string markText)
        {
            AddCurveData(key, new float[1]
            {
                value
            }, new string[1]
            {
                markText
            });
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="values">The values.</param>
        public void AddCurveData(string key, float[] values)
        {
            AddCurveData(key, values, null);
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="values">The values.</param>
        /// <param name="markTexts">The mark texts.</param>
        public void AddCurveData(string key, float[] values, string[] markTexts)
        {
            if (markTexts == null)
            {
                markTexts = new string[values.Length];
            }
            AddCurveData(key, values, markTexts, false);
            if (values != null && values.Length != 0)
            {
                AddCurveTime(values.Length);
            }
            Invalidate();
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="keys">The keys.</param>
        /// <param name="values">The values.</param>
        public void AddCurveData(string[] keys, float[] values)
        {
            AddCurveData(keys, values, null);
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="axisText">The axis text.</param>
        /// <param name="keys">The keys.</param>
        /// <param name="values">The values.</param>
        public void AddCurveData(string axisText, string[] keys, float[] values)
        {
            AddCurveData(axisText, keys, values, null);
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="keys">The keys.</param>
        /// <param name="values">The values.</param>
        /// <param name="markTexts">The mark texts.</param>
        /// <exception cref="ArgumentNullException">keys
        /// or
        /// values</exception>
        /// <exception cref="Exception">两个参数的数组长度不一致。
        /// or
        /// 两个参数的数组长度不一致。</exception>
        public void AddCurveData(string[] keys, float[] values, string[] markTexts)
        {
            if (keys == null)
            {
                throw new ArgumentNullException("keys");
            }
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }
            if (markTexts == null)
            {
                markTexts = new string[keys.Length];
            }
            if (keys.Length != values.Length)
            {
                throw new Exception("两个参数的数组长度不一致。");
            }
            if (keys.Length != markTexts.Length)
            {
                throw new Exception("两个参数的数组长度不一致。");
            }
            for (int i = 0; i < keys.Length; i++)
            {
                AddCurveData(keys[i], new float[1]
                {
                    values[i]
                }, new string[1]
                {
                    markTexts[i]
                }, false);
            }
            AddCurveTime(1);
            Invalidate();
        }

        /// <summary>
        /// Adds the curve data.
        /// </summary>
        /// <param name="axisText">The axis text.</param>
        /// <param name="keys">The keys.</param>
        /// <param name="values">The values.</param>
        /// <param name="markTexts">The mark texts.</param>
        /// <exception cref="ArgumentNullException">keys
        /// or
        /// values</exception>
        /// <exception cref="Exception">两个参数的数组长度不一致。
        /// or
        /// 两个参数的数组长度不一致。</exception>
        public void AddCurveData(string axisText, string[] keys, float[] values, string[] markTexts)
        {
            if (keys == null)
            {
                throw new ArgumentNullException("keys");
            }
            if (values == null)
            {
                throw new ArgumentNullException("values");
            }
            if (markTexts == null)
            {
                markTexts = new string[keys.Length];
            }
            if (keys.Length != values.Length)
            {
                throw new Exception("两个参数的数组长度不一致。");
            }
            if (keys.Length != markTexts.Length)
            {
                throw new Exception("两个参数的数组长度不一致。");
            }
            for (int i = 0; i < keys.Length; i++)
            {
                AddCurveData(keys[i], new float[1]
                {
                    values[i]
                }, new string[1]
                {
                    markTexts[i]
                }, false);
            }
            AddCurveTime(1, axisText);
            Invalidate();
        }

        /// <summary>
        /// Sets the curve visible.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="visible">if set to <c>true</c> [visible].</param>
        public void SetCurveVisible(string key, bool visible)
        {
            if (data_list.ContainsKey(key))
            {
                CurveItem CurveItem = data_list[key];
                CurveItem.Visible = visible;
                Invalidate();
            }
        }

        /// <summary>
        /// Sets the curve visible.
        /// </summary>
        /// <param name="keys">The keys.</param>
        /// <param name="visible">if set to <c>true</c> [visible].</param>
        public void SetCurveVisible(string[] keys, bool visible)
        {
            foreach (string key in keys)
            {
                if (data_list.ContainsKey(key))
                {
                    CurveItem CurveItem = data_list[key];
                    CurveItem.Visible = visible;
                }
            }
            Invalidate();
        }

        /// <summary>
        /// Adds the left auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        public void AddLeftAuxiliary(float value)
        {
            AddLeftAuxiliary(value, ColorLinesAndText);
        }

        /// <summary>
        /// Adds the left auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="lineColor">Color of the line.</param>
        public void AddLeftAuxiliary(float value, Color lineColor)
        {
            AddLeftAuxiliary(value, lineColor, 1f, true);
        }

        /// <summary>
        /// Adds the left auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="lineColor">Color of the line.</param>
        /// <param name="lineThickness">The line thickness.</param>
        /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
        public void AddLeftAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine)
        {
            AddAuxiliary(value, lineColor, lineThickness, isDashLine, true);
        }

        /// <summary>
        /// Adds the right auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        public void AddRightAuxiliary(float value)
        {
            AddRightAuxiliary(value, ColorLinesAndText);
        }

        /// <summary>
        /// Adds the right auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="lineColor">Color of the line.</param>
        public void AddRightAuxiliary(float value, Color lineColor)
        {
            AddRightAuxiliary(value, lineColor, 1f, true);
        }

        /// <summary>
        /// Adds the right auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="lineColor">Color of the line.</param>
        /// <param name="lineThickness">The line thickness.</param>
        /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
        public void AddRightAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine)
        {
            AddAuxiliary(value, lineColor, lineThickness, isDashLine, false);
        }

        /// <summary>
        /// Adds the auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="lineColor">Color of the line.</param>
        /// <param name="lineThickness">The line thickness.</param>
        /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
        /// <param name="isLeft">if set to <c>true</c> [is left].</param>
        private void AddAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine, bool isLeft)
        {
            auxiliary_lines.Add(new AuxiliaryLine
            {
                Value = value,
                LineColor = lineColor,
                PenDash = new Pen(lineColor)
                {
                    DashStyle = DashStyle.Custom,
                    DashPattern = new float[2]
                    {
                        5f,
                        5f
                    }
                },
                PenSolid = new Pen(lineColor),
                IsDashStyle = isDashLine,
                IsLeftFrame = isLeft,
                LineThickness = lineThickness,
                LineTextBrush = new SolidBrush(lineColor)
            });
            Invalidate();
        }

        /// <summary>
        /// Removes the auxiliary.
        /// </summary>
        /// <param name="value">The value.</param>
        public void RemoveAuxiliary(float value)
        {
            int num = 0;
            for (int num2 = auxiliary_lines.Count - 1; num2 >= 0; num2--)
            {
                if (auxiliary_lines[num2].Value == value)
                {
                    auxiliary_lines[num2].Dispose();
                    auxiliary_lines.RemoveAt(num2);
                    num++;
                }
            }
            if (num > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Removes all auxiliary.
        /// </summary>
        public void RemoveAllAuxiliary()
        {
            int count = auxiliary_lines.Count;
            auxiliary_lines.Clear();
            if (count > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Adds the auxiliary label.
        /// </summary>
        /// <param name="auxiliaryLable">The auxiliary lable.</param>
        public void AddAuxiliaryLabel(AuxiliaryLable auxiliaryLable)
        {
            auxiliary_Labels.Add(auxiliaryLable);
        }

        /// <summary>
        /// Removes the auxiliary lable.
        /// </summary>
        /// <param name="auxiliaryLable">The auxiliary lable.</param>
        public void RemoveAuxiliaryLable(AuxiliaryLable auxiliaryLable)
        {
            if (auxiliary_Labels.Remove(auxiliaryLable))
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Removes all auxiliary lable.
        /// </summary>
        public void RemoveAllAuxiliaryLable()
        {
            int count = auxiliary_Labels.Count;
            auxiliary_Labels.Clear();
            if (count > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Adds the mark text.
        /// </summary>
        /// <param name="markText">The mark text.</param>
        public void AddMarkText(MarkText markText)
        {
            MarkTexts.Add(markText);
            if (data_list.Count > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Adds the mark text.
        /// </summary>
        /// <param name="strCurveKey">The string curve key.</param>
        /// <param name="intValueIndex">Index of the int value.</param>
        /// <param name="strText">The string text.</param>
        /// <param name="textColor">Color of the text.</param>
        public void AddMarkText(string strCurveKey, int intValueIndex, string strText, Color? textColor = null)
        {
            AddMarkText(new MarkText() { CurveKey = strCurveKey, PositionStyle = MarkTextPositionStyle.Auto, Text = strText, TextColor = textColor, Index = intValueIndex });
        }

        /// <summary>
        /// Removes the mark text.
        /// </summary>
        /// <param name="markText">The mark text.</param>
        public void RemoveMarkText(MarkText markText)
        {
            MarkTexts.Remove(markText);
            if (data_list.Count > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// Removes all mark text.
        /// </summary>
        public void RemoveAllMarkText()
        {
            MarkTexts.Clear();
            if (data_list.Count > 0)
            {
                Invalidate();
            }
        }

        /// <summary>
        /// 引发 <see cref="E:System.Windows.Forms.Control.MouseMove" /> 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.MouseEventArgs" />。</param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            bool flag = false;
            foreach (KeyValuePair<string, CurveItem> item in data_list)
            {
                if (item.Value.TitleRegion.Contains(e.Location))
                {
                    flag = true;
                    break;
                }
            }
            Cursor = (flag ? Cursors.Hand : Cursors.Arrow);
        }

        /// <summary>
        /// Handles the <see cref="E:MouseDown" /> event.
        /// </summary>
        /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.MouseEventArgs" />。</param>
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            foreach (KeyValuePair<string, CurveItem> item in data_list)
            {
                if (item.Value.TitleRegion.Contains(e.Location))
                {
                    item.Value.LineRenderVisiable = !item.Value.LineRenderVisiable;
                    Invalidate();
                    break;
                }
            }
        }

        /// <summary>
        /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
        /// </summary>
        /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" />。</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                Graphics graphics = e.Graphics;
                graphics.SetGDIHigh();
                if (BackColor != Color.Transparent)
                {
                    graphics.Clear(BackColor);
                }
                int width = base.Width;
                int height = base.Height;
                if (width < 120 || height < 60)
                {
                    return;
                }
                Point[] array = new Point[4]
                {
                    new Point(leftRight - 1, upDowm - 8),
                    new Point(leftRight - 1, height - upDowm),
                    new Point(width - leftRight, height - upDowm),
                    new Point(width - leftRight, upDowm - 8)
                };
                graphics.DrawLine(pen_normal, array[0], array[1]);
                graphics.DrawLine(pen_normal, array[1], array[2]);
                if (isRenderRightCoordinate)
                {
                    graphics.DrawLine(pen_normal, array[2], array[3]);
                }

                if (!string.IsNullOrEmpty(value_title))
                {
                    graphics.DrawString(value_title, font_size9, brush_deep, new Rectangle(0, 0, width - 1, 20), format_center);
                }

                if (data_list.Count > 0)
                {
                    float num = leftRight + 10;
                    foreach (KeyValuePair<string, CurveItem> item in data_list)
                    {
                        if (item.Value.Visible)
                        {
                            var titleSize=graphics.MeasureString(item.Key, Font);
                            SolidBrush solidBrush = item.Value.LineRenderVisiable ? new SolidBrush(item.Value.LineColor) : new SolidBrush(Color.FromArgb(80, item.Value.LineColor));
                            graphics.FillRectangle(solidBrush, num + 8f, 24f, 20f, 14f);
                            graphics.DrawString(item.Key, Font, solidBrush, new PointF(num + 30f, 24f+(14 - titleSize.Height) / 2));
                            item.Value.TitleRegion = new RectangleF(num, 24f, 60f, 18f);
                            solidBrush.Dispose();
                            num += titleSize.Width + 30;
                        }
                    }
                }


                for (int i = 0; i < auxiliary_Labels.Count; i++)
                {
                    if (!string.IsNullOrEmpty(auxiliary_Labels[i].Text))
                    {
                        int num2 = (auxiliary_Labels[i].LocationX > 1f) ? ((int)auxiliary_Labels[i].LocationX) : ((int)(auxiliary_Labels[i].LocationX * (float)width));
                        int num3 = (int)graphics.MeasureString(auxiliary_Labels[i].Text, Font).Width + 3;
                        Point[] points = new Point[6]
                    {
                        new Point(num2, 11),
                        new Point(num2 + 10, 20),
                        new Point(num2 + num3 + 10, 20),
                        new Point(num2 + num3 + 10, 0),
                        new Point(num2 + 10, 0),
                        new Point(num2, 11)
                    };
                        graphics.FillPolygon(auxiliary_Labels[i].TextBack, points);
                        graphics.DrawString(auxiliary_Labels[i].Text, Font, auxiliary_Labels[i].TextBrush, new Rectangle(num2 + 7, 0, num3 + 3, 20), format_center);
                    }
                }
                ControlHelper.PaintTriangle(graphics, brush_deep, new Point(leftRight - 1, upDowm - 8), 4, GraphDirection.Upward);
                if (isRenderRightCoordinate)
                {
                    ControlHelper.PaintTriangle(graphics, brush_deep, new Point(width - leftRight, upDowm - 8), 4, GraphDirection.Upward);
                }
                for (int j = 0; j < auxiliary_lines.Count; j++)
                {
                    if (auxiliary_lines[j].IsLeftFrame)
                    {
                        auxiliary_lines[j].PaintValue = ControlHelper.ComputePaintLocationY(value_max_left, value_min_left, height - upDowm - upDowm, auxiliary_lines[j].Value) + (float)upDowm;
                    }
                    else
                    {
                        auxiliary_lines[j].PaintValue = ControlHelper.ComputePaintLocationY(value_max_right, value_min_right, height - upDowm - upDowm, auxiliary_lines[j].Value) + (float)upDowm;
                    }
                }
                for (int k = 0; k <= value_Segment; k++)
                {
                    float value = (float)((double)k * (double)(value_max_left - value_min_left) / (double)value_Segment + (double)value_min_left);
                    float num4 = ControlHelper.ComputePaintLocationY(value_max_left, value_min_left, height - upDowm - upDowm, value) + (float)upDowm;
                    if (IsNeedPaintDash(num4))
                    {
                        graphics.DrawLine(pen_normal, leftRight - 4, num4, leftRight - 1, num4);
                        RectangleF layoutRectangle = new RectangleF(0f, num4 - 9f, leftRight - 4, 20f);
                        graphics.DrawString(value.ToString(), font_size9, brush_deep, layoutRectangle, format_right);
                        if (isRenderRightCoordinate)
                        {
                            float num5 = (float)k * (value_max_right - value_min_right) / (float)value_Segment + value_min_right;
                            graphics.DrawLine(pen_normal, width - leftRight + 1, num4, width - leftRight + 4, num4);
                            layoutRectangle.Location = new PointF(width - leftRight + 4, num4 - 9f);
                            graphics.DrawString(num5.ToString(), font_size9, brush_deep, layoutRectangle, format_left);
                        }
                        if (k > 0 && value_IsRenderDashLine)
                        {
                            graphics.DrawLine(pen_dash, leftRight, num4, width - leftRight, num4);
                        }
                    }
                }
                if (value_IsRenderDashLine)
                {
                    if (value_IsAbscissaStrech)
                    {
                        float num6 = (float)(width - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
                        int num7 = CalculateDataCountByOffect(num6);
                        for (int l = 0; l < value_StrechDataCountMax; l += num7)
                        {
                            if (l > 0 && l < value_StrechDataCountMax - 1)
                            {
                                graphics.DrawLine(pen_dash, (float)l * num6 + (float)leftRight, upDowm, (float)l * num6 + (float)leftRight, height - upDowm - 1);
                            }
                            if (data_text != null && l < data_text.Length && (float)l * num6 + (float)leftRight < (float)(data_text.Length - 1) * num6 + (float)leftRight - 40f)
                            {
                                graphics.DrawString(layoutRectangle: new Rectangle((int)((float)l * num6), height - upDowm + 1, leftRight * 2, upDowm), s: data_text[l], font: font_size9, brush: brush_deep, format: format_center);
                            }
                        }
                        string[] array2 = data_text;
                        if (array2 != null && array2.Length > 1)
                        {
                            if (data_text.Length < value_StrechDataCountMax)
                            {
                                graphics.DrawLine(pen_dash, (float)(data_text.Length - 1) * num6 + (float)leftRight, upDowm, (float)(data_text.Length - 1) * num6 + (float)leftRight, height - upDowm - 1);
                            }
                            graphics.DrawString(layoutRectangle: new Rectangle((int)((float)(data_text.Length - 1) * num6 + (float)leftRight) - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
                        }
                    }
                    else if (value_IntervalAbscissaText > 0)
                    {
                        int num8 = width - 2 * leftRight + 1;
                        for (int m = leftRight; m < width - leftRight; m += value_IntervalAbscissaText)
                        {
                            if (m != leftRight)
                            {
                                graphics.DrawLine(pen_dash, m, upDowm, m, height - upDowm - 1);
                            }
                            if (data_text == null)
                            {
                                continue;
                            }
                            int num9 = (num8 > data_text.Length) ? data_text.Length : num8;
                            if (m - leftRight < data_text.Length && num9 - (m - leftRight) > 40)
                            {
                                if (data_text.Length <= num8)
                                {
                                    graphics.DrawString(layoutRectangle: new Rectangle(m - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[m - leftRight], font: font_size9, brush: brush_deep, format: format_center);
                                }
                                else
                                {
                                    graphics.DrawString(layoutRectangle: new Rectangle(m - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[m - leftRight + data_text.Length - num8], font: font_size9, brush: brush_deep, format: format_center);
                                }
                            }
                        }
                        string[] array3 = data_text;
                        if (array3 != null && array3.Length > 1)
                        {
                            if (data_text.Length >= num8)
                            {
                                graphics.DrawString(layoutRectangle: new Rectangle(width - leftRight - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
                            }
                            else
                            {
                                graphics.DrawLine(pen_dash, data_text.Length + leftRight - 1, upDowm, data_text.Length + leftRight - 1, height - upDowm - 1);
                                graphics.DrawString(layoutRectangle: new Rectangle(data_text.Length + leftRight - 1 - leftRight, height - upDowm + 1, leftRight * 2, upDowm), s: data_text[data_text.Length - 1], font: font_size9, brush: brush_deep, format: format_center);
                            }
                        }
                    }
                }
                for (int n = 0; n < auxiliary_lines.Count; n++)
                {
                    if (auxiliary_lines[n].IsLeftFrame)
                    {
                        graphics.DrawLine(auxiliary_lines[n].GetPen(), leftRight - 4, auxiliary_lines[n].PaintValue, leftRight - 1, auxiliary_lines[n].PaintValue);
                        graphics.DrawString(layoutRectangle: new RectangleF(0f, auxiliary_lines[n].PaintValue - 9f, leftRight - 4, 20f), s: auxiliary_lines[n].Value.ToString(), font: font_size9, brush: auxiliary_lines[n].LineTextBrush, format: format_right);
                    }
                    else
                    {
                        graphics.DrawLine(auxiliary_lines[n].GetPen(), width - leftRight + 1, auxiliary_lines[n].PaintValue, width - leftRight + 4, auxiliary_lines[n].PaintValue);
                        graphics.DrawString(layoutRectangle: new RectangleF(width - leftRight + 4, auxiliary_lines[n].PaintValue - 9f, leftRight - 4, 20f), s: auxiliary_lines[n].Value.ToString(), font: font_size9, brush: auxiliary_lines[n].LineTextBrush, format: format_left);
                    }
                    graphics.DrawLine(auxiliary_lines[n].GetPen(), leftRight, auxiliary_lines[n].PaintValue, width - leftRight, auxiliary_lines[n].PaintValue);
                }
                if (value_IsAbscissaStrech)
                {
                    foreach (MarkText MarkText in MarkTexts)
                    {
                        foreach (KeyValuePair<string, CurveItem> item2 in data_list)
                        {
                            if (item2.Value.Visible && item2.Value.LineRenderVisiable && !(item2.Key != MarkText.CurveKey))
                            {
                                float[] data = item2.Value.Data;
                                if (data != null && data.Length > 1)
                                {
                                    float num10 = (float)(width - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
                                    if (MarkText.Index >= 0 && MarkText.Index < item2.Value.Data.Length)
                                    {
                                        PointF pointF = new PointF((float)leftRight + (float)MarkText.Index * num10, ControlHelper.ComputePaintLocationY(item2.Value.IsLeftFrame ? value_max_left : value_max_right, item2.Value.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, item2.Value.Data[MarkText.Index]) + (float)upDowm);
                                        graphics.FillEllipse(new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 3f, pointF.Y - 3f, 6f, 6f));
                                        switch ((MarkText.PositionStyle == MarkTextPositionStyle.Auto) ? MarkText.CalculateDirectionFromDataIndex(item2.Value.Data, MarkText.Index) : MarkText.PositionStyle)
                                        {
                                            case MarkTextPositionStyle.Left:
                                                graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 100f, pointF.Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
                                                break;
                                            case MarkTextPositionStyle.Up:
                                                graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 100f, pointF.Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                                                break;
                                            case MarkTextPositionStyle.Right:
                                                graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X + (float)MarkText.MarkTextOffect, pointF.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
                                                break;
                                            case MarkTextPositionStyle.Down:
                                                graphics.DrawString(MarkText.Text, Font, new SolidBrush(MarkText.TextColor ?? item2.Value.LineColor), new RectangleF(pointF.X - 100f, pointF.Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                                                break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    foreach (CurveItem value2 in data_list.Values)
                    {
                        if (value2.Visible && value2.LineRenderVisiable)
                        {
                            float[] data2 = value2.Data;
                            if (data2 != null && data2.Length > 1)
                            {
                                float num11 = (float)(width - leftRight * 2) * 1f / (float)(value_StrechDataCountMax - 1);
                                PointF[] array4 = new PointF[value2.Data.Length];
                                for (int num12 = 0; num12 < value2.Data.Length; num12++)
                                {
                                    array4[num12].X = (float)leftRight + (float)num12 * num11;
                                    array4[num12].Y = ControlHelper.ComputePaintLocationY(value2.IsLeftFrame ? value_max_left : value_max_right, value2.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, value2.Data[num12]) + (float)upDowm;
                                    if (!string.IsNullOrEmpty(value2.MarkText[num12]))
                                    {
                                        using (Brush brush = new SolidBrush(value2.LineColor))
                                        {
                                            graphics.FillEllipse(brush, new RectangleF(array4[num12].X - 3f, array4[num12].Y - 3f, 6f, 6f));
                                            switch (MarkText.CalculateDirectionFromDataIndex(value2.Data, num12))
                                            {
                                                case MarkTextPositionStyle.Left:
                                                    graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X - 100f, array4[num12].Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
                                                    break;
                                                case MarkTextPositionStyle.Up:
                                                    graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X - 100f, array4[num12].Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                                                    break;
                                                case MarkTextPositionStyle.Right:
                                                    graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X + (float)MarkText.MarkTextOffect, array4[num12].Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
                                                    break;
                                                case MarkTextPositionStyle.Down:
                                                    graphics.DrawString(value2.MarkText[num12], Font, brush, new RectangleF(array4[num12].X - 100f, array4[num12].Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                                                    break;
                                            }
                                        }
                                    }
                                }
                                using (Pen pen2 = new Pen(value2.LineColor, value2.LineThickness))
                                {
                                    if (value2.IsSmoothCurve)
                                    {
                                        graphics.DrawCurve(pen2, array4);
                                    }
                                    else
                                    {
                                        graphics.DrawLines(pen2, array4);
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    foreach (MarkText MarkText2 in MarkTexts)
                    {
                        foreach (KeyValuePair<string, CurveItem> item3 in data_list)
                        {
                            if (item3.Value.Visible && item3.Value.LineRenderVisiable && !(item3.Key != MarkText2.CurveKey))
                            {
                                float[] data3 = item3.Value.Data;
                                if (data3 != null && data3.Length > 1 && MarkText2.Index >= 0 && MarkText2.Index < item3.Value.Data.Length)
                                {
                                    PointF pointF2 = new PointF(leftRight + MarkText2.Index, ControlHelper.ComputePaintLocationY(item3.Value.IsLeftFrame ? value_max_left : value_max_right, item3.Value.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, item3.Value.Data[MarkText2.Index]) + (float)upDowm);
                                    graphics.FillEllipse(new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 3f, pointF2.Y - 3f, 6f, 6f));
                                    switch ((MarkText2.PositionStyle == MarkTextPositionStyle.Auto) ? MarkText.CalculateDirectionFromDataIndex(item3.Value.Data, MarkText2.Index) : MarkText2.PositionStyle)
                                    {
                                        case MarkTextPositionStyle.Left:
                                            graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 100f, pointF2.Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
                                            break;
                                        case MarkTextPositionStyle.Up:
                                            graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 100f, pointF2.Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                                            break;
                                        case MarkTextPositionStyle.Right:
                                            graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X + (float)MarkText.MarkTextOffect, pointF2.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
                                            break;
                                        case MarkTextPositionStyle.Down:
                                            graphics.DrawString(MarkText2.Text, Font, new SolidBrush(MarkText2.TextColor ?? item3.Value.LineColor), new RectangleF(pointF2.X - 100f, pointF2.Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                                            break;
                                    }
                                }
                            }
                        }
                    }
                    foreach (CurveItem value3 in data_list.Values)
                    {
                        if (value3.Visible && value3.LineRenderVisiable)
                        {
                            float[] data4 = value3.Data;
                            if (data4 != null && data4.Length > 1)
                            {
                                int num13 = width - 2 * leftRight + 1;
                                PointF[] array5;
                                if (value3.Data.Length <= num13)
                                {
                                    array5 = new PointF[value3.Data.Length];
                                    for (int num14 = 0; num14 < value3.Data.Length; num14++)
                                    {
                                        array5[num14].X = leftRight + num14;
                                        array5[num14].Y = ControlHelper.ComputePaintLocationY(value3.IsLeftFrame ? value_max_left : value_max_right, value3.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, value3.Data[num14]) + (float)upDowm;
                                        DrawMarkPoint(graphics, value3.MarkText[num14], array5[num14], value3.LineColor, MarkText.CalculateDirectionFromDataIndex(value3.Data, num14));
                                    }
                                }
                                else
                                {
                                    array5 = new PointF[num13];
                                    for (int num15 = 0; num15 < array5.Length; num15++)
                                    {
                                        int num16 = num15 + value3.Data.Length - num13;
                                        array5[num15].X = leftRight + num15;
                                        array5[num15].Y = ControlHelper.ComputePaintLocationY(value3.IsLeftFrame ? value_max_left : value_max_right, value3.IsLeftFrame ? value_min_left : value_min_right, height - upDowm - upDowm, value3.Data[num16]) + (float)upDowm;
                                        DrawMarkPoint(graphics, value3.MarkText[num16], array5[num15], value3.LineColor, MarkText.CalculateDirectionFromDataIndex(value3.Data, num16));
                                    }
                                }
                                using (Pen pen3 = new Pen(value3.LineColor, value3.LineThickness))
                                {
                                    if (value3.IsSmoothCurve)
                                    {
                                        graphics.DrawCurve(pen3, array5);
                                    }
                                    else
                                    {
                                        graphics.DrawLines(pen3, array5);
                                    }
                                }
                            }
                        }
                    }
                }
                base.OnPaint(e);
            }
            catch (Exception exc)
            {
                e.Graphics.DrawString(exc.Message, this.Font, Brushes.Black, 10, 10);
            }
        }

        /// <summary>
        /// Draws the mark point.
        /// </summary>
        /// <param name="g">The g.</param>
        /// <param name="markText">The mark text.</param>
        /// <param name="center">The center.</param>
        /// <param name="color">The color.</param>
        /// <param name="markTextPosition">The mark text position.</param>
        private void DrawMarkPoint(Graphics g, string markText, PointF center, Color color, MarkTextPositionStyle markTextPosition)
        {
            if (!string.IsNullOrEmpty(markText))
            {
                using (Brush brush = new SolidBrush(color))
                {
                    DrawMarkPoint(g, markText, center, brush, markTextPosition);
                }
            }
        }

        /// <summary>
        /// Draws the mark point.
        /// </summary>
        /// <param name="g">The g.</param>
        /// <param name="markText">The mark text.</param>
        /// <param name="center">The center.</param>
        /// <param name="brush">The brush.</param>
        /// <param name="markTextPosition">The mark text position.</param>
        private void DrawMarkPoint(Graphics g, string markText, PointF center, Brush brush, MarkTextPositionStyle markTextPosition)
        {
            if (!string.IsNullOrEmpty(markText))
            {
                g.FillEllipse(brush, new RectangleF(center.X - 3f, center.Y - 3f, 6f, 6f));
                switch (markTextPosition)
                {
                    case MarkTextPositionStyle.Left:
                        g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height, 100 - MarkText.MarkTextOffect, Font.Height * 2), format_right);
                        break;
                    case MarkTextPositionStyle.Up:
                        g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y - (float)Font.Height - (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                        break;
                    case MarkTextPositionStyle.Right:
                        g.DrawString(markText, Font, brush, new RectangleF(center.X + (float)MarkText.MarkTextOffect, center.Y - (float)Font.Height, 100f, Font.Height * 2), format_left);
                        break;
                    case MarkTextPositionStyle.Down:
                        g.DrawString(markText, Font, brush, new RectangleF(center.X - 100f, center.Y + (float)MarkText.MarkTextOffect, 200f, Font.Height + 2), format_center);
                        break;
                }
            }
        }

        /// <summary>
        /// Determines whether [is need paint dash] [the specified paint value].
        /// </summary>
        /// <param name="paintValue">The paint value.</param>
        /// <returns><c>true</c> if [is need paint dash] [the specified paint value]; otherwise, <c>false</c>.</returns>
        private bool IsNeedPaintDash(float paintValue)
        {
            for (int i = 0; i < auxiliary_lines.Count; i++)
            {
                if (Math.Abs(auxiliary_lines[i].PaintValue - paintValue) < (float)font_size9.Height)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Calculates the data count by offect.
        /// </summary>
        /// <param name="offect">The offect.</param>
        /// <returns>System.Int32.</returns>
        private int CalculateDataCountByOffect(float offect)
        {
            if (value_IntervalAbscissaText > 0)
            {
                return value_IntervalAbscissaText;
            }
            if (offect > 40f)
            {
                return 1;
            }
            offect = 40f / offect;
            return (int)Math.Ceiling(offect);
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources.
        /// </summary>
        /// <param name="disposing">为 true 则释放托管资源和非托管资源;为 false 则仅释放非托管资源。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && components != null)
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// Initializes the component.
        /// </summary>
        private void InitializeComponent()
        {
            SuspendLayout();
            base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
            BackColor = System.Drawing.Color.Transparent;
            base.Name = "HslCurve";
            base.Size = new System.Drawing.Size(417, 205);
            ResumeLayout(false);
        }
    }
}

 

最后的话

如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星星吧

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值