(六十七)c#Winform自定义控件-柱状图-HZHControls
官网
前提
入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
如果觉得写的还行,请点个 star 支持一下吧
麻烦博客下方点个【推荐】,谢谢
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 点个星星吧
作者:冰封一夏
出处:http://www.cnblogs.com/bfyx/
HZHControls官网:http://www.hzhcontrols.cn
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,
且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
GitHub:https://github.com/kwwwvagaa/NetWinformControl
码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git