(六十七)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

用处及效果

调用示例

 1  this.ucBarChart1.SetDataSource(new double[] { random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100) });
 2             this.ucBarChart2.SetDataSource(new double[] { random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100) }, new string[] { "张三", "李四", "王五", "赵六", "田七" });
 3             this.ucBarChart3.SetDataSource(new double[] { random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100) }, new string[] { "张三", "李四", "王五", "赵六", "田七" });
 4 
 5             this.ucBarChart4.SetDataSource(new double[] { random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100) }, new string[] { "张三", "李四", "王五", "赵六", "田七" });
 6             this.ucBarChart4.AddAuxiliaryLine(60, Color.Red, "及格线超长占位符");
 7 
 8             this.ucBarChart5.SetDataSource(new double[] { random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100), random.Next(50, 100) }, new string[] { "张三", "李四", "王五", "赵六", "田七" });
 9             this.ucBarChart5.AddAuxiliaryLine(50, Color.Black, "及格线");
10 
11            
12             var ds = new double[5][];
13             for (int i = 0; i < ds.Length; i++)
14             {
15                 ds[i] = new double[] { random.Next(50, 100), random.Next(50, 100), random.Next(50, 100) };
16             }
17             this.ucBarChart6.BarChartItems = new HZH_Controls.Controls.BarChartItem[] { new HZH_Controls.Controls.BarChartItem(Color.Red, "语文"), new HZH_Controls.Controls.BarChartItem(Color.Blue, "英语"), new HZH_Controls.Controls.BarChartItem(Color.Orange, "数学") };
18             this.ucBarChart6.SetDataSource(ds, new string[] { "张三", "李四", "王五", "赵六", "田七" });
19             this.ucBarChart6.AddAuxiliaryLine(60, Color.Black);
20 
21             var ds2 = new List<double[]>();
22             for (int i = 0; i < 20; i++)
23             {
24                 ds2.Add(new double[] { random.Next(800, 2000), random.Next(100, 200) });
25             }
26             var titles = new List<string>();
27             double dblSum = ds2.Sum(p=>p[0]);
28             for (int i = 0; i < ds2.Count; i++)
29             {
30                 titles.Add("员工" + (i + 1) + "\n" + (ds2[i][0] / dblSum).ToString("0.0%"));
31             }
32             this.ucBarChart7.BarChartItems = new HZH_Controls.Controls.BarChartItem[] { new HZH_Controls.Controls.BarChartItem(Color.Green, "合格"), new HZH_Controls.Controls.BarChartItem(Color.Red, "次品") };
33             this.ucBarChart7.SetDataSource(ds2.ToArray(), titles.ToArray());
34             this.ucBarChart7.AddAuxiliaryLine(1000, Color.Black, "标准线");

 

准备工作

GDI画图,不懂可以先百度一下

另外用到了(一)c#Winform自定义控件-基类控件 不知道的可以先前往看一下

开始

我们先理一下思路,

我们需要值,x轴,y轴,辅助线,项列表,标题,以及一些颜色等

添加一个类UCBarChart ,继承UCControlBase

添加一些控制属性

  1 /// <summary>
  2         /// The auxiliary lines
  3         /// </summary>
  4         private List<AuxiliaryLine> auxiliary_lines;
  5 
  6         /// <summary>
  7         /// The value maximum left
  8         /// </summary>
  9         private int value_max_left = -1;
 10 
 11         /// <summary>
 12         /// The value minimum left
 13         /// </summary>
 14         private int value_min_left = 0;
 15 
 16         /// <summary>
 17         /// The value segment
 18         /// </summary>
 19         private int value_Segment = 5;
 20 
 21         /// <summary>
 22         /// The data values
 23         /// </summary>
 24         private double[][] data_values = null;
 25 
 26         /// <summary>
 27         /// The data texts
 28         /// </summary>
 29         private string[] data_texts = null;
 30 
 31         ///// <summary>
 32         ///// The data colors
 33         ///// </summary>
 34         //private Color[] data_colors = null;
 35 
 36         /// <summary>
 37         /// The brush deep
 38         /// </summary>
 39         private Brush brush_deep = null;
 40 
 41         /// <summary>
 42         /// The pen normal
 43         /// </summary>
 44         private Pen pen_normal = null;
 45 
 46         /// <summary>
 47         /// The pen dash
 48         /// </summary>
 49         private Pen pen_dash = null;
 50 
 51         /// <summary>
 52         /// The bar back color
 53         /// </summary>
 54         //private Color barBackColor = Color.FromArgb(255, 77, 59);
 55 
 56         /// <summary>
 57         /// The use gradient
 58         /// </summary>
 59         private bool useGradient = false;
 60 
 61         /// <summary>
 62         /// The color deep
 63         /// </summary>
 64         private Color color_deep = Color.FromArgb(150, 255, 77, 59);
 65 
 66         /// <summary>
 67         /// The color dash
 68         /// </summary>
 69         private Color color_dash = Color.FromArgb(50, 255, 77, 59);
 70 
 71         /// <summary>
 72         /// The format left
 73         /// </summary>
 74         private StringFormat format_left = null;
 75 
 76         /// <summary>
 77         /// The format right
 78         /// </summary>
 79         private StringFormat format_right = null;
 80 
 81         /// <summary>
 82         /// The format center
 83         /// </summary>
 84         private StringFormat format_center = null;
 85 
 86         /// <summary>
 87         /// The value is render dash line
 88         /// </summary>
 89         private bool value_IsRenderDashLine = true;
 90 
 91         /// <summary>
 92         /// The is show bar value
 93         /// </summary>
 94         private bool isShowBarValue = true;
 95 
 96         /// <summary>
 97         /// The show bar value format
 98         /// </summary>
 99         private string showBarValueFormat = "{0}";
100 
101         /// <summary>
102         /// The value title
103         /// </summary>
104         private string value_title = "";
105 
106         /// <summary>
107         /// The bar percent width
108         /// </summary>
109         private float barPercentWidth = 0.9f;
110 
111         /// <summary>
112         /// The components
113         /// </summary>
114         private IContainer components = null;
115 
116         /// <summary>
117         /// 获取或设置控件的背景色。
118         /// </summary>
119         /// <value>The color of the back.</value>
120         /// <PermissionSet>
121         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
122         /// </PermissionSet>
123         [Browsable(true)]
124         [Description("获取或设置控件的背景色")]
125         [Category("自定义")]
126         [DefaultValue(typeof(Color), "Transparent")]
127         [EditorBrowsable(EditorBrowsableState.Always)]
128         public override Color BackColor
129         {
130             get
131             {
132                 return base.BackColor;
133             }
134             set
135             {
136                 base.BackColor = value;
137             }
138         }
139 
140         /// <summary>
141         /// Gets or sets the text.
142         /// </summary>
143         /// <value>The text.</value>
144         [Browsable(true)]
145         [Description("获取或设置当前控件的文本")]
146         [Category("自定义")]
147         [EditorBrowsable(EditorBrowsableState.Always)]
148         [Bindable(true)]
149         [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
150         public override string Text
151         {
152             get
153             {
154                 return base.Text;
155             }
156             set
157             {
158                 base.Text = value;
159                 Invalidate();
160             }
161         }
162 
163         /// <summary>
164         /// 获取或设置控件的前景色。
165         /// </summary>
166         /// <value>The color of the fore.</value>
167         /// <PermissionSet>
168         ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
169         /// </PermissionSet>
170         [Browsable(true)]
171         [Description("获取或设置控件的前景色")]
172         [Category("自定义")]
173         [EditorBrowsable(EditorBrowsableState.Always)]
174         public override Color ForeColor
175         {
176             get
177             {
178                 return base.ForeColor;
179             }
180             set
181             {
182                 base.ForeColor = value;
183             }
184         }
185 
186         /// <summary>
187         /// Gets or sets the color lines and text.
188         /// </summary>
189         /// <value>The color lines and text.</value>
190         [Category("自定义")]
191         [Description("获取或设置坐标轴及相关信息文本的颜色")]
192         [Browsable(true)]
193         [DefaultValue(typeof(Color), "DimGray")]
194         public Color ColorLinesAndText
195         {
196             get
197             {
198                 return color_deep;
199             }
200             set
201             {
202                 color_deep = value;
203                 InitializationColor();
204                 Invalidate();
205             }
206         }
207 
208         /// <summary>
209         /// Gets or sets a value indicating whether [use gradient].
210         /// </summary>
211         /// <value><c>true</c> if [use gradient]; otherwise, <c>false</c>.</value>
212         [Category("自定义")]
213         [Description("获取或设置本条形图控件是否使用渐进色")]
214         [Browsable(true)]
215         [DefaultValue(false)]
216         public bool UseGradient
217         {
218             get
219             {
220                 return useGradient;
221             }
222             set
223             {
224                 useGradient = value;
225                 Invalidate();
226             }
227         }
228 
229         /// <summary>
230         /// Gets or sets the color dash lines.
231         /// </summary>
232         /// <value>The color dash lines.</value>
233         [Category("自定义")]
234         [Description("获取或设置虚线的颜色")]
235         [Browsable(true)]
236         [DefaultValue(typeof(Color), "LightGray")]
237         public Color ColorDashLines
238         {
239             get
240             {
241                 return color_dash;
242             }
243             set
244             {
245                 color_dash = value;
246                 if (pen_dash != null)
247                     pen_dash.Dispose();
248                 pen_dash = new Pen(color_dash);
249                 Invalidate();
250             }
251         }
252 
253         /// <summary>
254         /// Gets or sets a value indicating whether this instance is render dash line.
255         /// </summary>
256         /// <value><c>true</c> if this instance is render dash line; otherwise, <c>false</c>.</value>
257         [Category("自定义")]
258         [Description("获取或设置虚线是否进行显示")]
259         [Browsable(true)]
260         [DefaultValue(true)]
261         public bool IsRenderDashLine
262         {
263             get
264             {
265                 return value_IsRenderDashLine;
266             }
267             set
268             {
269                 value_IsRenderDashLine = value;
270                 Invalidate();
271             }
272         }
273 
274         /// <summary>
275         /// Gets or sets the value segment.
276         /// </summary>
277         /// <value>The value segment.</value>
278         [Category("自定义")]
279         [Description("获取或设置图形的纵轴分段数")]
280         [Browsable(true)]
281         [DefaultValue(5)]
282         public int ValueSegment
283         {
284             get
285             {
286                 return value_Segment;
287             }
288             set
289             {
290                 value_Segment = value;
291                 Invalidate();
292             }
293         }
294 
295         /// <summary>
296         /// Gets or sets the value maximum left.
297         /// </summary>
298         /// <value>The value maximum left.</value>
299         [Category("自定义")]
300         [Description("获取或设置图形的左纵坐标的最大值,该值必须大于最小值,该值为负数,最大值即为自动适配。")]
301         [Browsable(true)]
302         [DefaultValue(-1)]
303         public int ValueMaxLeft
304         {
305             get
306             {
307                 return value_max_left;
308             }
309             set
310             {
311                 value_max_left = value;
312                 Invalidate();
313             }
314         }
315 
316         /// <summary>
317         /// Gets or sets the value minimum left.
318         /// </summary>
319         /// <value>The value minimum left.</value>
320         [Category("自定义")]
321         [Description("获取或设置图形的左纵坐标的最小值,该值必须小于最大值")]
322         [Browsable(true)]
323         [DefaultValue(0)]
324         public int ValueMinLeft
325         {
326             get
327             {
328                 return value_min_left;
329             }
330             set
331             {
332                 if (value < value_max_left)
333                 {
334                     value_min_left = value;
335                     Invalidate();
336                 }
337             }
338         }
339 
340         /// <summary>
341         /// Gets or sets the title.
342         /// </summary>
343         /// <value>The title.</value>
344         [Category("自定义")]
345         [Description("获取或设置图标的标题信息")]
346         [Browsable(true)]
347         [DefaultValue("")]
348         public string Title
349         {
350             get
351             {
352                 return value_title;
353             }
354             set
355             {
356                 value_title = value;
357                 Invalidate();
358             }
359         }
360 
361         /// <summary>
362         /// Gets or sets a value indicating whether this instance is show bar value.
363         /// </summary>
364         /// <value><c>true</c> if this instance is show bar value; otherwise, <c>false</c>.</value>
365         [Category("自定义")]
366         [Description("获取或设置是否显示柱状图的值文本")]
367         [Browsable(true)]
368         [DefaultValue(true)]
369         public bool IsShowBarValue
370         {
371             get
372             {
373                 return isShowBarValue;
374             }
375             set
376             {
377                 isShowBarValue = value;
378                 Invalidate();
379             }
380         }
381 
382         /// <summary>
383         /// Gets or sets the show bar value format.
384         /// </summary>
385         /// <value>The show bar value format.</value>
386         [Category("自定义")]
387         [Description("获取或设置柱状图显示值的格式化信息,可以带单位")]
388         [Browsable(true)]
389         [DefaultValue("")]
390         public string ShowBarValueFormat
391         {
392             get
393             {
394                 return showBarValueFormat;
395             }
396             set
397             {
398                 showBarValueFormat = value;
399                 Invalidate();
400             }
401         }
402 
403         private BarChartItem[] barChartItems = new BarChartItem[] { new BarChartItem() };
404         [Category("自定义")]
405         [Description("获取或设置柱状图的项目")]
406         [Browsable(true)]
407         public BarChartItem[] BarChartItems
408         {
409             get { return barChartItems; }
410             set { barChartItems = value; }
411         }
412         [Category("自定义")]
413         [Description("获取或设置是否显示柱状图的项目名称")]
414         [Browsable(true)]
415         public bool ShowChartItemName { get; set; }

做一些初始化数据

 1  public UCBarChart()
 2         {
 3             InitializeComponent();
 4             ConerRadius = 10;
 5             ForeColor = Color.FromArgb(150, 255, 77, 59);
 6             FillColor = Color.FromArgb(243, 220, 219);
 7             format_left = new StringFormat
 8             {
 9                 LineAlignment = StringAlignment.Center,
10                 Alignment = StringAlignment.Near
11             };
12             format_right = new StringFormat
13             {
14                 LineAlignment = StringAlignment.Center,
15                 Alignment = StringAlignment.Far
16             };
17             format_center = new StringFormat
18             {
19                 LineAlignment = StringAlignment.Center,
20                 Alignment = StringAlignment.Center
21             };
22             auxiliary_lines = new List<AuxiliaryLine>();
23             pen_dash = new Pen(color_dash);
24             pen_dash.DashStyle = DashStyle.Custom;
25             pen_dash.DashPattern = new float[2]
26             {
27                 5f,
28                 5f
29             };
30             InitializationColor();
31             SetStyle(ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true);
32             SetStyle(ControlStyles.ResizeRedraw, true);
33             SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
34             SetStyle(ControlStyles.AllPaintingInWmPaint, true);
35 
36             if (DesignMode)
37             {
38                 barChartItems = new BarChartItem[] { new BarChartItem() };
39 
40                 data_values = new double[5][];
41                 for (int i = 0; i < data_values.Length; i++)
42                 {
43                     data_values[i] = new double[] { i + 1 };
44                 }
45             }
46 
47         }

设置数据源的函数

 1 /// <summary>
 2         /// Sets the data source.
 3         /// </summary>
 4         /// <param name="data">The data.</param>
 5         public void SetDataSource(double[] data)
 6         {
 7             SetDataSource(data, null);
 8         }
 9 
10         public void SetDataSource(double[][] data)
11         {
12             SetDataSource(data, null);
13         }
14         /// <summary>
15         /// Sets the data source.
16         /// </summary>
17         /// <param name="data">The data.</param>
18         /// <param name="texts">X texts</param>
19         public void SetDataSource(double[] data, string[] texts)
20         {
21             data_values = new double[data.Length][];
22             for (int i = 0; i < data.Length; i++)
23             {
24                 data_values[i] = new double[] { data[i] };
25             }
26             if (barChartItems == null || barChartItems.Length <= 0)
27                 barChartItems = new BarChartItem[] { new BarChartItem() };
28             data_texts = texts;
29             Invalidate();
30         }
31         public void SetDataSource(double[][] data, string[] texts)
32         {
33             data_values = data;
34             if (barChartItems == null || barChartItems.Length <= 0)
35                 barChartItems = new BarChartItem[] { new BarChartItem() };
36             data_texts = texts;
37             Invalidate();
38         }

重绘

  1 protected override void OnPaint(PaintEventArgs e)
  2         {
  3             base.OnPaint(e);
  4             Graphics graphics = e.Graphics;
  5             graphics.SmoothingMode = SmoothingMode.HighQuality;
  6             graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
  7             PaintMain(graphics, base.Width, base.Height);
  8         }
  9 
 10         /// <summary>
 11         /// Paints the main.
 12         /// </summary>
 13         /// <param name="g">The g.</param>
 14         /// <param name="width">The width.</param>
 15         /// <param name="height">The height.</param>
 16         private void PaintMain(Graphics g, int width, int height)
 17         {
 18             if (barChartItems == null || barChartItems.Length <= 0)
 19             {
 20                 if (DesignMode)
 21                 {
 22                     barChartItems = new BarChartItem[] { new BarChartItem() };
 23                 }
 24                 else
 25                 {
 26                     return;
 27                 }
 28             }
 29             if (data_values == null && DesignMode)
 30             {
 31                 data_values = new double[5][];
 32                 for (int i = 0; i < data_values.Length; i++)
 33                 {
 34                     data_values[i] = new double[] { i + 1 };
 35                 }
 36             }
 37 
 38             double num = (data_values != null && data_values.Length != 0) ? ChartsHelper.CalculateMaxSectionFrom(data_values) : 5;
 39             if (value_max_left > 0)
 40             {
 41                 num = value_max_left;
 42             }
 43             int intLeftX = (int)g.MeasureString(num.ToString(), Font).Width + 3;
 44             if (intLeftX < 50)
 45             {
 46                 intLeftX = 50;
 47             }
 48             //处理辅助线左侧间距
 49             if (auxiliary_lines != null && auxiliary_lines.Count > 0)
 50             {
 51                 var maxAuxiliaryWidth = auxiliary_lines.Max(p => g.MeasureString((p.Tip + "" + p.Value), Font).Width);
 52                 if (intLeftX < maxAuxiliaryWidth)
 53                 {
 54                     intLeftX = (int)maxAuxiliaryWidth + 5;
 55                 }
 56             }
 57             int intRightX = 20;
 58             //顶部距离
 59             int intTopY = 25;
 60             if (!string.IsNullOrEmpty(value_title))
 61             {
 62                 intTopY += 20;
 63             }
 64             //写标题
 65             if (!string.IsNullOrEmpty(value_title))
 66             {
 67                 g.DrawString(value_title, Font, brush_deep, new Rectangle(0, 0, width - 1, intTopY - 10), format_center);
 68             }
 69             //画项目名称颜色
 70             if (ShowChartItemName && !(barChartItems.Length == 1 && string.IsNullOrEmpty(barChartItems[0].ItemName)))
 71             {
 72                 int intItemNameRowCount = 0;
 73                 int intItemNameWidth = 0;
 74                 int intItemNameComCount = 0;
 75 
 76                 intItemNameWidth = (int)barChartItems.Max(p => g.MeasureString(p.ItemName, Font).Width) + 40;
 77                 intItemNameComCount = this.Width / intItemNameWidth;
 78                 intItemNameRowCount = barChartItems.Length / intItemNameComCount + (barChartItems.Length % intItemNameComCount != 0 ? 1 : 0);
 79                 int intItemNameHeight = (int)g.MeasureString("A", Font).Height;
 80 
 81                 for (int i = 0; i < intItemNameRowCount; i++)
 82                 {
 83                     int intLeft = (this.Width - (intItemNameWidth * ((i == intItemNameRowCount - 1) ? (barChartItems.Length % intItemNameComCount) : intItemNameComCount))) / 2;
 84                     int intTop = intTopY - 15 + intItemNameHeight * i + 10;
 85                     for (int j = i * intItemNameComCount; j < barChartItems.Length && j < (i + 1) * intItemNameComCount; j++)
 86                     {
 87                         Rectangle rectColor = new Rectangle(intLeft + (j % intItemNameComCount) * intItemNameWidth, intTop, 20, intItemNameHeight);
 88                         g.FillRectangle(new SolidBrush(barChartItems[j].BarBackColor), rectColor);
 89                         g.DrawString(barChartItems[j].ItemName, Font, new SolidBrush(ForeColor), new Point(rectColor.Right + 2, rectColor.Top));
 90                     }
 91                 }
 92                 intTopY += intItemNameRowCount * (intItemNameHeight + 20);
 93             }
 94 
 95             int intBottomY = 25;
 96             //处理x坐标文字高度
 97             if (data_texts != null && data_texts.Length > 0)
 98             {
 99                 var maxTextsHeight = data_texts.Max(p => g.MeasureString(p, Font).Height);
100                 if (intBottomY < maxTextsHeight)
101                     intBottomY = (int)maxTextsHeight + 5;
102             }
103             //画xy轴
104             Point[] array2 = new Point[3]
105             {
106                 new Point(intLeftX, intTopY - 8),
107                 new Point(intLeftX, height - intBottomY),
108                 new Point(width - intRightX+5, height - intBottomY)
109             };
110             g.DrawLine(pen_normal, array2[0], array2[1]);
111             g.DrawLine(pen_normal, array2[1], array2[2]);
112             ChartsHelper.PaintTriangle(g, brush_deep, new Point(intLeftX, intTopY - 8), 4, GraphDirection.Upward);
113             ChartsHelper.PaintTriangle(g, brush_deep, new Point(width - intRightX + 5, height - intBottomY), 4, GraphDirection.Rightward);
114 
115 
116             //画横向分割线
117             for (int j = 0; j <= value_Segment; j++)
118             {
119                 float value = (float)((double)j * (double)(num - value_min_left) / (double)value_Segment + (double)value_min_left);
120                 float num6 = ChartsHelper.ComputePaintLocationY((float)num, value_min_left, height - intTopY - intBottomY, value) + (float)intTopY;
121                 if (IsNeedPaintDash(num6))
122                 {
123                     g.DrawLine(pen_normal, intLeftX - 4, num6, intLeftX - 1, num6);
124                     g.DrawString(layoutRectangle: new RectangleF(0f, num6 - 19f, intLeftX - 4, 40f), s: value.ToString(), font: Font, brush: brush_deep, format: format_right);
125                     if (j > 0 && value_IsRenderDashLine)
126                     {
127                         g.DrawLine(pen_dash, intLeftX, num6, width - intRightX, num6);
128                     }
129                 }
130             }
131             //计算辅助线y坐标
132             for (int i = 0; i < auxiliary_lines.Count; i++)
133             {
134                 auxiliary_lines[i].PaintValue = ChartsHelper.ComputePaintLocationY((float)num, value_min_left, height - intTopY - intBottomY, auxiliary_lines[i].Value) + (float)intTopY;
135             }
136 
137             //画辅助线
138             for (int k = 0; k < auxiliary_lines.Count; k++)
139             {
140                 g.DrawLine(auxiliary_lines[k].GetPen(), intLeftX - 4, auxiliary_lines[k].PaintValue, intLeftX - 1, auxiliary_lines[k].PaintValue);
141                 g.DrawString(layoutRectangle: new RectangleF(0f, auxiliary_lines[k].PaintValue - 9f, intLeftX - 4, 20f), s: auxiliary_lines[k].Tip + "" + auxiliary_lines[k].Value.ToString(), font: Font, brush: auxiliary_lines[k].LineTextBrush, format: format_right);
142                 g.DrawLine(auxiliary_lines[k].GetPen(), intLeftX, auxiliary_lines[k].PaintValue, width - intRightX, auxiliary_lines[k].PaintValue);
143             }
144             if (data_values == null || data_values.Length == 0 || data_values.Max(p => p.Length) <= 0)
145             {
146                 return;
147             }
148 
149             //x轴分隔宽度
150             float fltSplitWidth = (float)(width - intLeftX - 1 - intRightX) * 1f / (float)data_values.Length;
151             for (int i = 0; i < data_values.Length; i++)
152             {
153                 int intItemSplitCount = barChartItems.Length;
154                 float _fltSplitWidth = fltSplitWidth * barPercentWidth / intItemSplitCount;
155                 float _fltLeft = (float)i * fltSplitWidth + (1f - barPercentWidth) / 2f * fltSplitWidth + (float)intLeftX;
156                 for (int j = 0; j < data_values[i].Length; j++)
157                 {
158                     if (j >= intItemSplitCount)
159                     {
160                         break;
161                     }
162                     float fltValueY = ChartsHelper.ComputePaintLocationY((float)num, value_min_left, height - intTopY - intBottomY, (float)data_values[i][j]) + (float)intTopY;
163 
164 
165                     RectangleF rect = new RectangleF(_fltLeft + _fltSplitWidth * j + (1F - barChartItems[j].BarPercentWidth) * _fltSplitWidth / 2f, fltValueY,
166                     _fltSplitWidth * barChartItems[j].BarPercentWidth, (float)(height - intBottomY) - fltValueY);
167 
168                     Color color = barChartItems[j].BarBackColor;
169 
170                     //画柱状
171                     if (useGradient)
172                     {
173                         if (rect.Height > 0f)
174                         {
175                             using (LinearGradientBrush brush = new LinearGradientBrush(new PointF(rect.X, rect.Y + rect.Height), new PointF(rect.X, rect.Y), ChartsHelper.GetColorLight(color), color))
176                             {
177                                 g.FillRectangle(brush, rect);
178                             }
179                         }
180                     }
181                     else
182                     {
183                         using (Brush brush2 = new SolidBrush(color))
184                         {
185                             g.FillRectangle(brush2, rect);
186                         }
187                     }
188                     //写值文字
189                     if (isShowBarValue)
190                     {
191                         using (Brush brush3 = new SolidBrush(ForeColor))
192                         {
193                             g.DrawString(layoutRectangle: new RectangleF(rect.Left - 50f, fltValueY - (float)Font.Height - 2f, _fltSplitWidth + 100f, Font.Height + 2), s: string.Format(showBarValueFormat, data_values[i][j]), font: Font, brush: brush3, format: format_center);
194                         }
195                     }
196                 }
197 
198                 //写x轴文字
199                 if (data_texts != null && i < data_texts.Length)
200                 {
201                     g.DrawString(layoutRectangle: new RectangleF((float)i * fltSplitWidth + (float)intLeftX - 50f, height - intBottomY - 1, fltSplitWidth + 100f, intBottomY + 1), s: data_texts[i], font: Font, brush: brush_deep, format: format_center);
202                 }
203             }
204         }

辅助线相关函数

 1 #region 辅助线    English:Guide
 2         /// <summary>
 3         /// Adds the left auxiliary.
 4         /// </summary>
 5         /// <param name="value">The value.</param>
 6         public void AddAuxiliaryLine(float value, string strTip = "")
 7         {
 8             AddAuxiliaryLine(value, ColorLinesAndText, strTip);
 9         }
10 
11         /// <summary>
12         /// Adds the left auxiliary.
13         /// </summary>
14         /// <param name="value">The value.</param>
15         /// <param name="lineColor">Color of the line.</param>
16         public void AddAuxiliaryLine(float value, Color lineColor, string strTip = "")
17         {
18             AddAuxiliaryLine(value, lineColor, 1f, true, strTip);
19         }
20 
21         /// <summary>
22         /// Adds the left auxiliary.
23         /// </summary>
24         /// <param name="value">The value.</param>
25         /// <param name="lineColor">Color of the line.</param>
26         /// <param name="lineThickness">The line thickness.</param>
27         /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
28         public void AddAuxiliaryLine(float value, Color lineColor, float lineThickness, bool isDashLine, string strTip = "")
29         {
30             AddAuxiliary(value, lineColor, lineThickness, isDashLine, strTip);
31         }
32 
33         /// <summary>
34         /// Adds the auxiliary.
35         /// </summary>
36         /// <param name="value">The value.</param>
37         /// <param name="lineColor">Color of the line.</param>
38         /// <param name="lineThickness">The line thickness.</param>
39         /// <param name="isDashLine">if set to <c>true</c> [is dash line].</param>
40         /// <param name="isLeft">if set to <c>true</c> [is left].</param>
41         private void AddAuxiliary(float value, Color lineColor, float lineThickness, bool isDashLine, string strTip = "")
42         {
43             auxiliary_lines.Add(new AuxiliaryLine
44             {
45                 Value = value,
46                 LineColor = lineColor,
47                 PenDash = new Pen(lineColor)
48                 {
49                     DashStyle = DashStyle.Custom,
50                     DashPattern = new float[2]
51                     {
52                         5f,
53                         5f
54                     }
55                 },
56                 PenSolid = new Pen(lineColor),
57                 IsDashStyle = isDashLine,
58                 LineThickness = lineThickness,
59                 LineTextBrush = new SolidBrush(lineColor),
60                 Tip = strTip
61             });
62             Invalidate();
63         }
64 
65         /// <summary>
66         /// Removes the auxiliary.
67         /// </summary>
68         /// <param name="value">The value.</param>
69         public void RemoveAuxiliary(float value)
70         {
71             int num = 0;
72             for (int num2 = auxiliary_lines.Count - 1; num2 >= 0; num2--)
73             {
74                 if (auxiliary_lines[num2].Value == value)
75                 {
76                     auxiliary_lines[num2].Dispose();
77                     auxiliary_lines.RemoveAt(num2);
78                     num++;
79                 }
80             }
81             if (num > 0)
82             {
83                 Invalidate();
84             }
85         }
86 
87         /// <summary>
88         /// Removes all auxiliary.
89         /// </summary>
90         public void RemoveAllAuxiliary()
91         {
92             int count = auxiliary_lines.Count;
93             auxiliary_lines.Clear();
94             if (count > 0)
95             {
96                 Invalidate();
97             }
98         }
99         #endregion

完整代码,请前往开源地址查看吧。

最后的话

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

posted @ 2019-09-17 15:23 冰封一夏 阅读(...) 评论(...) 编辑 收藏