zoukankan      html  css  js  c++  java
  • (七十四)c#Winform自定义控件-金字塔图表-HZHControls

    官网

    http://www.hzhcontrols.com

    前提

    入行已经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+画图,不懂的先百度了解下

    开始

    添加一些枚举

     1  public enum FunelChartAlignment
     2     {
     3         /// <summary>
     4         /// The left
     5         /// </summary>
     6         Left,
     7         /// <summary>
     8         /// The center
     9         /// </summary>
    10         Center,
    11         /// <summary>
    12         /// The right
    13         /// </summary>
    14         Right
    15     }
    16 
    17  public enum FunelChartDirection
    18     {
    19         /// <summary>
    20         /// Up
    21         /// </summary>
    22         UP,
    23         /// <summary>
    24         /// Down
    25         /// </summary>
    26         Down
    27     }

    添加一个项实体

     1   public class FunelChartItem
     2     {
     3         /// <summary>
     4         /// Gets or sets the text.
     5         /// </summary>
     6         /// <value>The text.</value>
     7         public string Text { get; set; }
     8         /// <summary>
     9         /// Gets or sets the value.
    10         /// </summary>
    11         /// <value>The value.</value>
    12         public float Value { get; set; }
    13         /// <summary>
    14         /// Gets or sets the color of the value.
    15         /// </summary>
    16         /// <value>The color of the value.</value>
    17         public System.Drawing.Color? ValueColor { get; set; }
    18         /// <summary>
    19         /// Gets or sets the color of the text fore.
    20         /// </summary>
    21         /// <value>The color of the text fore.</value>
    22         public System.Drawing.Color? TextForeColor { get; set; }
    23     }

    添加一个类UCFunnelChart ,继承UserControl

    添加一些控制属性

      1 /// <summary>
      2         /// The title
      3         /// </summary>
      4         private string title;
      5         /// <summary>
      6         /// Gets or sets the title.
      7         /// </summary>
      8         /// <value>The title.</value>
      9         [Browsable(true)]
     10         [Category("自定义")]
     11         [Description("获取或设置标题")]
     12         public string Title
     13         {
     14             get { return title; }
     15             set
     16             {
     17                 title = value;
     18                 ResetTitleSize();
     19                 Invalidate();
     20             }
     21         }
     22 
     23         /// <summary>
     24         /// The title font
     25         /// </summary>
     26         private Font titleFont = new Font("微软雅黑", 12);
     27         /// <summary>
     28         /// Gets or sets the title font.
     29         /// </summary>
     30         /// <value>The title font.</value>
     31         [Browsable(true)]
     32         [Category("自定义")]
     33         [Description("获取或设置标题字体")]
     34         public Font TitleFont
     35         {
     36             get { return titleFont; }
     37             set
     38             {
     39                 titleFont = value;
     40                 ResetTitleSize();
     41                 Invalidate();
     42             }
     43         }
     44 
     45         /// <summary>
     46         /// The title fore color
     47         /// </summary>
     48         private Color titleForeColor = Color.Black;
     49         /// <summary>
     50         /// Gets or sets the color of the title fore.
     51         /// </summary>
     52         /// <value>The color of the title fore.</value>
     53         [Browsable(true)]
     54         [Category("自定义")]
     55         [Description("获取或设置标题文字颜色")]
     56         public Color TitleForeColor
     57         {
     58             get { return titleForeColor; }
     59             set
     60             {
     61                 titleForeColor = value;
     62                 Invalidate();
     63             }
     64         }
     65         /// <summary>
     66         /// The items
     67         /// </summary>
     68         private FunelChartItem[] items;
     69         /// <summary>
     70         /// Gets or sets the items.
     71         /// </summary>
     72         /// <value>The items.</value>
     73         [Browsable(true)]
     74         [Category("自定义")]
     75         [Description("获取或设置项目")]
     76         public FunelChartItem[] Items
     77         {
     78             get { return items; }
     79             set
     80             {
     81                 items = value;
     82                 Invalidate();
     83             }
     84         }
     85 
     86         /// <summary>
     87         /// The direction
     88         /// </summary>
     89         private FunelChartDirection direction = FunelChartDirection.UP;
     90         /// <summary>
     91         /// Gets or sets the direction.
     92         /// </summary>
     93         /// <value>The direction.</value>
     94         [Browsable(true)]
     95         [Category("自定义")]
     96         [Description("获取或设置方向")]
     97         public FunelChartDirection Direction
     98         {
     99             get { return direction; }
    100             set
    101             {
    102                 direction = value;
    103                 Invalidate();
    104             }
    105         }
    106 
    107         /// <summary>
    108         /// The alignment
    109         /// </summary>
    110         private FunelChartAlignment alignment = FunelChartAlignment.Center;
    111         /// <summary>
    112         /// Gets or sets the alignment.
    113         /// </summary>
    114         /// <value>The alignment.</value>
    115         [Browsable(true)]
    116         [Category("自定义")]
    117         [Description("获取或设置对齐方式")]
    118         public FunelChartAlignment Alignment
    119         {
    120             get { return alignment; }
    121             set
    122             {
    123                 alignment = value;
    124                 Invalidate();
    125             }
    126         }
    127 
    128         /// <summary>
    129         /// The item text align
    130         /// </summary>
    131         private FunelChartAlignment itemTextAlign = FunelChartAlignment.Center;
    132         /// <summary>
    133         /// Gets or sets the item text align.
    134         /// </summary>
    135         /// <value>The item text align.</value>
    136         [Browsable(true)]
    137         [Category("自定义")]
    138         [Description("获取或设置文字位置")]
    139         public FunelChartAlignment ItemTextAlign
    140         {
    141             get { return itemTextAlign; }
    142             set
    143             {
    144                 itemTextAlign = value;
    145                 ResetWorkingRect();
    146                 Invalidate();
    147             }
    148         }
    149         /// <summary>
    150         /// The show value
    151         /// </summary>
    152         private bool showValue = false;
    153         /// <summary>
    154         /// Gets or sets a value indicating whether [show value].
    155         /// </summary>
    156         /// <value><c>true</c> if [show value]; otherwise, <c>false</c>.</value>
    157         [Browsable(true)]
    158         [Category("自定义")]
    159         [Description("获取或设置是否显示值")]
    160         public bool ShowValue
    161         {
    162             get { return showValue; }
    163             set
    164             {
    165                 showValue = value;
    166                 Invalidate();
    167             }
    168         }
    169 
    170 
    171         /// <summary>
    172         /// The value format
    173         /// </summary>
    174         private string valueFormat = "0.##";
    175         /// <summary>
    176         /// Gets or sets the value format.
    177         /// </summary>
    178         /// <value>The value format.</value>
    179         [Browsable(true)]
    180         [Category("自定义")]
    181         [Description("获取或设置值格式化")]
    182         public string ValueFormat
    183         {
    184             get { return valueFormat; }
    185             set
    186             {
    187                 valueFormat = value;
    188                 Invalidate();
    189             }
    190         }
    191 
    192         /// <summary>
    193         /// The m rect working
    194         /// </summary>
    195         RectangleF m_rectWorking;
    196         /// <summary>
    197         /// The m title size
    198         /// </summary>
    199         SizeF m_titleSize = SizeF.Empty;
    200         /// <summary>
    201         /// The int split width
    202         /// </summary>
    203         int intSplitWidth = 1;

    构造函数初始化

     1  public UCFunnelChart()
     2         {
     3             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
     4             this.SetStyle(ControlStyles.DoubleBuffer, true);
     5             this.SetStyle(ControlStyles.ResizeRedraw, true);
     6             this.SetStyle(ControlStyles.Selectable, true);
     7             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
     8             this.SetStyle(ControlStyles.UserPaint, true);
     9             this.FontChanged += UCFunnelChart_FontChanged;
    10             Font = new Font("微软雅黑", 8);
    11 
    12             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    13             this.SizeChanged += UCFunnelChart_SizeChanged;
    14             Size = new System.Drawing.Size(150, 150);
    15             items = new FunelChartItem[0];
    16             if (ControlHelper.IsDesignMode())
    17             {
    18                 items = new FunelChartItem[5];
    19                 for (int i = 0; i < 5; i++)
    20                 {
    21                     items[i] = new FunelChartItem()
    22                     {
    23                         Text = "item" + i,
    24                         Value = 10 * (i + 1)
    25                     };
    26                 }
    27             }
    28         }

    当大小及状态改变时 重新计算工作区域

     1   void UCFunnelChart_FontChanged(object sender, EventArgs e)
     2         {
     3             ResetWorkingRect();
     4         }
     5 
     6         /// <summary>
     7         /// Handles the SizeChanged event of the UCFunnelChart control.
     8         /// </summary>
     9         /// <param name="sender">The source of the event.</param>
    10         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    11         void UCFunnelChart_SizeChanged(object sender, EventArgs e)
    12         {
    13             ResetWorkingRect();
    14         }
    15 
    16         /// <summary>
    17         /// Resets the working rect.
    18         /// </summary>
    19         private void ResetWorkingRect()
    20         {
    21             if (itemTextAlign == FunelChartAlignment.Center)
    22             {
    23                 m_rectWorking = new RectangleF(0, m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10), this.Width, this.Height - (m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10)));
    24             }
    25             else if (itemTextAlign == FunelChartAlignment.Left)
    26             {
    27                 float fltMax = 0;
    28                 if (items != null && items.Length > 0)
    29                 {
    30                     using (Graphics g = this.CreateGraphics())
    31                     {
    32                         fltMax = items.Max(p => g.MeasureString(p.Text, Font).Width);
    33                     }
    34                 }
    35                 m_rectWorking = new RectangleF(fltMax, m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10), this.Width - fltMax, this.Height - (m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10)));
    36             }
    37             else
    38             {
    39                 float fltMax = 0;
    40                 if (items != null && items.Length > 0)
    41                 {
    42                     using (Graphics g = this.CreateGraphics())
    43                     {
    44                         fltMax = items.Max(p => g.MeasureString(p.Text, Font).Width);
    45                     }
    46                 }
    47                 m_rectWorking = new RectangleF(0, m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10), this.Width - fltMax, this.Height - (m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10)));
    48             }
    49         }
    50 
    51         /// <summary>
    52         /// Resets the size of the title.
    53         /// </summary>
    54         private void ResetTitleSize()
    55         {
    56             if (string.IsNullOrEmpty(title))
    57             {
    58                 m_titleSize = SizeF.Empty;
    59             }
    60             else
    61             {
    62                 using (Graphics g = this.CreateGraphics())
    63                 {
    64                     m_titleSize = g.MeasureString(title, titleFont);
    65                     m_titleSize.Height += 20;
    66                 }
    67             }
    68             ResetWorkingRect();
    69         }

    重绘

      1 protected override void OnPaint(PaintEventArgs e)
      2         {
      3             base.OnPaint(e);
      4             var g = e.Graphics;
      5             g.SetGDIHigh();
      6 
      7             if (!string.IsNullOrEmpty(title))
      8             {
      9                 g.DrawString(title, titleFont, new SolidBrush(titleForeColor), new RectangleF(0, 0, this.Width, m_titleSize.Height), new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
     10             }
     11 
     12             if (items == null || items.Length <= 0)
     13             {
     14                 g.DrawString("没有数据", Font, new SolidBrush(Color.Black), this.m_rectWorking, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
     15                 return;
     16             }
     17 
     18             List<FunelChartItem> lstItems;
     19             if (direction == FunelChartDirection.UP)
     20             {
     21                 lstItems = items.OrderBy(p => p.Value).ToList();
     22             }
     23             else
     24             {
     25                 lstItems = items.OrderByDescending(p => p.Value).ToList();
     26             }
     27 
     28             List<RectangleF> lstRects = new List<RectangleF>();
     29             List<GraphicsPath> lstPaths = new List<GraphicsPath>();
     30             float maxValue = lstItems.Max(p => p.Value);
     31             float dblSplitHeight = m_rectWorking.Height / lstItems.Count;
     32             for (int i = 0; i < lstItems.Count; i++)
     33             {
     34                 FunelChartItem item = lstItems[i];
     35                 if (item.ValueColor == null || item.ValueColor == Color.Empty || item.ValueColor == Color.Transparent)
     36                     item.ValueColor = ControlHelper.Colors[i];
     37 
     38                 switch (alignment)
     39                 {
     40                     case FunelChartAlignment.Left:
     41                         lstRects.Add(new RectangleF(m_rectWorking.Left, m_rectWorking.Top + dblSplitHeight * i, item.Value / maxValue * m_rectWorking.Width, dblSplitHeight));
     42                         break;
     43                     case FunelChartAlignment.Center:
     44                         lstRects.Add(new RectangleF(m_rectWorking.Left + (m_rectWorking.Width - (item.Value / maxValue * m_rectWorking.Width)) / 2, m_rectWorking.Top + dblSplitHeight * i, item.Value / maxValue * m_rectWorking.Width, dblSplitHeight));
     45                         break;
     46                     case FunelChartAlignment.Right:
     47                         lstRects.Add(new RectangleF(m_rectWorking.Right - (item.Value / maxValue * m_rectWorking.Width), m_rectWorking.Top + dblSplitHeight * i, item.Value / maxValue * m_rectWorking.Width, dblSplitHeight));
     48                         break;
     49                 }
     50             }
     51 
     52             for (int i = 0; i < lstRects.Count; i++)
     53             {
     54                 var rect = lstRects[i];
     55                 GraphicsPath path = new GraphicsPath();
     56                 List<PointF> lstPoints = new List<PointF>();
     57                 if (direction == FunelChartDirection.UP)
     58                 {
     59                     switch (alignment)
     60                     {
     61                         case FunelChartAlignment.Left:
     62                             lstPoints.Add(new PointF(rect.Left, rect.Top));
     63                             if (i != 0)
     64                             {
     65                                 lstPoints.Add(new PointF(lstRects[i - 1].Right, rect.Top));
     66                             }
     67                             break;
     68                         case FunelChartAlignment.Center:
     69                             if (i == 0)
     70                             {
     71                                 lstPoints.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
     72                             }
     73                             else
     74                             {
     75                                 lstPoints.Add(new PointF(lstRects[i - 1].Left, rect.Top));
     76                                 lstPoints.Add(new PointF(lstRects[i - 1].Right, rect.Top));
     77                             }
     78                             break;
     79                         case FunelChartAlignment.Right:
     80                             if (i == 0)
     81                             {
     82                                 lstPoints.Add(new PointF(rect.Right, rect.Top));
     83                             }
     84                             else
     85                             {
     86                                 lstPoints.Add(new PointF(rect.Right - lstRects[i - 1].Width, rect.Top));
     87                                 lstPoints.Add(new PointF(rect.Right, rect.Top));
     88                             }
     89                             break;
     90                     }
     91                     lstPoints.Add(new PointF(rect.Right, rect.Bottom - intSplitWidth));
     92                     lstPoints.Add(new PointF(rect.Left, rect.Bottom - intSplitWidth));
     93                 }
     94                 else
     95                 {
     96                     lstPoints.Add(new PointF(rect.Left, rect.Top + intSplitWidth));
     97                     lstPoints.Add(new PointF(rect.Right, rect.Top + intSplitWidth));
     98                     switch (alignment)
     99                     {
    100                         case FunelChartAlignment.Left:
    101                             if (i == lstRects.Count - 1)
    102                             {
    103                                 lstPoints.Add(new PointF(rect.Left, rect.Bottom));
    104                             }
    105                             else
    106                             {
    107                                 lstPoints.Add(new PointF(lstRects[i + 1].Right, rect.Bottom));
    108                                 lstPoints.Add(new PointF(rect.Left, rect.Bottom));
    109                             }
    110                             break;
    111                         case FunelChartAlignment.Center:
    112                             if (i == lstRects.Count - 1)
    113                             {
    114                                 lstPoints.Add(new PointF(rect.Left + rect.Width / 2, rect.Bottom));
    115                             }
    116                             else
    117                             {
    118                                 lstPoints.Add(new PointF(lstRects[i + 1].Right, rect.Bottom));
    119                                 lstPoints.Add(new PointF(lstRects[i + 1].Left, rect.Bottom));
    120                             }
    121                             break;
    122                         case FunelChartAlignment.Right:
    123                             if (i == lstRects.Count - 1)
    124                             {
    125                                 lstPoints.Add(new PointF(rect.Right, rect.Bottom));
    126                             }
    127                             else
    128                             {
    129                                 lstPoints.Add(new PointF(rect.Right, rect.Bottom));
    130                                 lstPoints.Add(new PointF(lstRects[i + 1].Left, rect.Bottom));
    131                             }
    132                             break;
    133                     }
    134                 }
    135                 path.AddLines(lstPoints.ToArray());
    136                 path.CloseAllFigures();
    137                 // g.DrawPath(new Pen(new SolidBrush(lstItems[i].ValueColor.Value)), path);
    138                 g.FillPath(new SolidBrush(lstItems[i].ValueColor.Value), path);
    139 
    140                 //写字
    141                 if (itemTextAlign == FunelChartAlignment.Center)
    142                 {
    143                     g.DrawString(lstItems[i].Text + (ShowValue ? lstItems[i].Value.ToString("
    " + valueFormat) : ""), Font, new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? Color.White : lstItems[i].TextForeColor.Value), rect, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
    144                 }
    145                 else if (itemTextAlign == FunelChartAlignment.Left)
    146                 {
    147                     g.DrawString(lstItems[i].Text + (ShowValue ? lstItems[i].Value.ToString("
    " + valueFormat) : ""), Font, new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value), new RectangleF(0, rect.Top, rect.Left, rect.Height), new StringFormat() { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Center });
    148                     g.DrawLine(new Pen(new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value)), rect.Left, rect.Top + rect.Height / 2, rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
    149                 }
    150                 else
    151                 {
    152                     g.DrawString(lstItems[i].Text + (ShowValue ? lstItems[i].Value.ToString("
    " + valueFormat) : ""), Font, new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value), new RectangleF(rect.Right, rect.Top, this.Width - rect.Right, rect.Height), new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center });
    153                     g.DrawLine(new Pen(new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value)), rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, rect.Right, rect.Top + rect.Height / 2);
    154                 }
    155             }
    156         }

    完整代码

      1 // ***********************************************************************
      2 // Assembly         : HZH_Controls
      3 // Created          : 2019-09-26
      4 //
      5 // ***********************************************************************
      6 // <copyright file="UCFunnelChart.cs">
      7 //     Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
      8 // </copyright>
      9 //
     10 // Blog: https://www.cnblogs.com/bfyx
     11 // GitHub:https://github.com/kwwwvagaa/NetWinformControl
     12 // gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
     13 //
     14 // If you use this code, please keep this note.
     15 // ***********************************************************************
     16 using System;
     17 using System.Collections.Generic;
     18 using System.Linq;
     19 using System.Text;
     20 using System.Windows.Forms;
     21 using System.Drawing;
     22 using System.Drawing.Drawing2D;
     23 using System.ComponentModel;
     24 
     25 namespace HZH_Controls.Controls
     26 {
     27     /// <summary>
     28     /// Class UCFunnelChart.
     29     /// Implements the <see cref="System.Windows.Forms.UserControl" />
     30     /// </summary>
     31     /// <seealso cref="System.Windows.Forms.UserControl" />
     32     public class UCFunnelChart : UserControl
     33     {
     34         /// <summary>
     35         /// The title
     36         /// </summary>
     37         private string title;
     38         /// <summary>
     39         /// Gets or sets the title.
     40         /// </summary>
     41         /// <value>The title.</value>
     42         [Browsable(true)]
     43         [Category("自定义")]
     44         [Description("获取或设置标题")]
     45         public string Title
     46         {
     47             get { return title; }
     48             set
     49             {
     50                 title = value;
     51                 ResetTitleSize();
     52                 Invalidate();
     53             }
     54         }
     55 
     56         /// <summary>
     57         /// The title font
     58         /// </summary>
     59         private Font titleFont = new Font("微软雅黑", 12);
     60         /// <summary>
     61         /// Gets or sets the title font.
     62         /// </summary>
     63         /// <value>The title font.</value>
     64         [Browsable(true)]
     65         [Category("自定义")]
     66         [Description("获取或设置标题字体")]
     67         public Font TitleFont
     68         {
     69             get { return titleFont; }
     70             set
     71             {
     72                 titleFont = value;
     73                 ResetTitleSize();
     74                 Invalidate();
     75             }
     76         }
     77 
     78         /// <summary>
     79         /// The title fore color
     80         /// </summary>
     81         private Color titleForeColor = Color.Black;
     82         /// <summary>
     83         /// Gets or sets the color of the title fore.
     84         /// </summary>
     85         /// <value>The color of the title fore.</value>
     86         [Browsable(true)]
     87         [Category("自定义")]
     88         [Description("获取或设置标题文字颜色")]
     89         public Color TitleForeColor
     90         {
     91             get { return titleForeColor; }
     92             set
     93             {
     94                 titleForeColor = value;
     95                 Invalidate();
     96             }
     97         }
     98         /// <summary>
     99         /// The items
    100         /// </summary>
    101         private FunelChartItem[] items;
    102         /// <summary>
    103         /// Gets or sets the items.
    104         /// </summary>
    105         /// <value>The items.</value>
    106         [Browsable(true)]
    107         [Category("自定义")]
    108         [Description("获取或设置项目")]
    109         public FunelChartItem[] Items
    110         {
    111             get { return items; }
    112             set
    113             {
    114                 items = value;
    115                 Invalidate();
    116             }
    117         }
    118 
    119         /// <summary>
    120         /// The direction
    121         /// </summary>
    122         private FunelChartDirection direction = FunelChartDirection.UP;
    123         /// <summary>
    124         /// Gets or sets the direction.
    125         /// </summary>
    126         /// <value>The direction.</value>
    127         [Browsable(true)]
    128         [Category("自定义")]
    129         [Description("获取或设置方向")]
    130         public FunelChartDirection Direction
    131         {
    132             get { return direction; }
    133             set
    134             {
    135                 direction = value;
    136                 Invalidate();
    137             }
    138         }
    139 
    140         /// <summary>
    141         /// The alignment
    142         /// </summary>
    143         private FunelChartAlignment alignment = FunelChartAlignment.Center;
    144         /// <summary>
    145         /// Gets or sets the alignment.
    146         /// </summary>
    147         /// <value>The alignment.</value>
    148         [Browsable(true)]
    149         [Category("自定义")]
    150         [Description("获取或设置对齐方式")]
    151         public FunelChartAlignment Alignment
    152         {
    153             get { return alignment; }
    154             set
    155             {
    156                 alignment = value;
    157                 Invalidate();
    158             }
    159         }
    160 
    161         /// <summary>
    162         /// The item text align
    163         /// </summary>
    164         private FunelChartAlignment itemTextAlign = FunelChartAlignment.Center;
    165         /// <summary>
    166         /// Gets or sets the item text align.
    167         /// </summary>
    168         /// <value>The item text align.</value>
    169         [Browsable(true)]
    170         [Category("自定义")]
    171         [Description("获取或设置文字位置")]
    172         public FunelChartAlignment ItemTextAlign
    173         {
    174             get { return itemTextAlign; }
    175             set
    176             {
    177                 itemTextAlign = value;
    178                 ResetWorkingRect();
    179                 Invalidate();
    180             }
    181         }
    182         /// <summary>
    183         /// The show value
    184         /// </summary>
    185         private bool showValue = false;
    186         /// <summary>
    187         /// Gets or sets a value indicating whether [show value].
    188         /// </summary>
    189         /// <value><c>true</c> if [show value]; otherwise, <c>false</c>.</value>
    190         [Browsable(true)]
    191         [Category("自定义")]
    192         [Description("获取或设置是否显示值")]
    193         public bool ShowValue
    194         {
    195             get { return showValue; }
    196             set
    197             {
    198                 showValue = value;
    199                 Invalidate();
    200             }
    201         }
    202 
    203 
    204         /// <summary>
    205         /// The value format
    206         /// </summary>
    207         private string valueFormat = "0.##";
    208         /// <summary>
    209         /// Gets or sets the value format.
    210         /// </summary>
    211         /// <value>The value format.</value>
    212         [Browsable(true)]
    213         [Category("自定义")]
    214         [Description("获取或设置值格式化")]
    215         public string ValueFormat
    216         {
    217             get { return valueFormat; }
    218             set
    219             {
    220                 valueFormat = value;
    221                 Invalidate();
    222             }
    223         }
    224 
    225         /// <summary>
    226         /// The m rect working
    227         /// </summary>
    228         RectangleF m_rectWorking;
    229         /// <summary>
    230         /// The m title size
    231         /// </summary>
    232         SizeF m_titleSize = SizeF.Empty;
    233         /// <summary>
    234         /// The int split width
    235         /// </summary>
    236         int intSplitWidth = 1;
    237 
    238         /// <summary>
    239         /// Initializes a new instance of the <see cref="UCFunnelChart"/> class.
    240         /// </summary>
    241         public UCFunnelChart()
    242         {
    243             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
    244             this.SetStyle(ControlStyles.DoubleBuffer, true);
    245             this.SetStyle(ControlStyles.ResizeRedraw, true);
    246             this.SetStyle(ControlStyles.Selectable, true);
    247             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    248             this.SetStyle(ControlStyles.UserPaint, true);
    249             this.FontChanged += UCFunnelChart_FontChanged;
    250             Font = new Font("微软雅黑", 8);
    251 
    252             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    253             this.SizeChanged += UCFunnelChart_SizeChanged;
    254             Size = new System.Drawing.Size(150, 150);
    255             items = new FunelChartItem[0];
    256             if (ControlHelper.IsDesignMode())
    257             {
    258                 items = new FunelChartItem[5];
    259                 for (int i = 0; i < 5; i++)
    260                 {
    261                     items[i] = new FunelChartItem()
    262                     {
    263                         Text = "item" + i,
    264                         Value = 10 * (i + 1)
    265                     };
    266                 }
    267             }
    268         }
    269 
    270         /// <summary>
    271         /// Handles the FontChanged event of the UCFunnelChart control.
    272         /// </summary>
    273         /// <param name="sender">The source of the event.</param>
    274         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    275         void UCFunnelChart_FontChanged(object sender, EventArgs e)
    276         {
    277             ResetWorkingRect();
    278         }
    279 
    280         /// <summary>
    281         /// Handles the SizeChanged event of the UCFunnelChart control.
    282         /// </summary>
    283         /// <param name="sender">The source of the event.</param>
    284         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    285         void UCFunnelChart_SizeChanged(object sender, EventArgs e)
    286         {
    287             ResetWorkingRect();
    288         }
    289 
    290         /// <summary>
    291         /// Resets the working rect.
    292         /// </summary>
    293         private void ResetWorkingRect()
    294         {
    295             if (itemTextAlign == FunelChartAlignment.Center)
    296             {
    297                 m_rectWorking = new RectangleF(0, m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10), this.Width, this.Height - (m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10)));
    298             }
    299             else if (itemTextAlign == FunelChartAlignment.Left)
    300             {
    301                 float fltMax = 0;
    302                 if (items != null && items.Length > 0)
    303                 {
    304                     using (Graphics g = this.CreateGraphics())
    305                     {
    306                         fltMax = items.Max(p => g.MeasureString(p.Text, Font).Width);
    307                     }
    308                 }
    309                 m_rectWorking = new RectangleF(fltMax, m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10), this.Width - fltMax, this.Height - (m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10)));
    310             }
    311             else
    312             {
    313                 float fltMax = 0;
    314                 if (items != null && items.Length > 0)
    315                 {
    316                     using (Graphics g = this.CreateGraphics())
    317                     {
    318                         fltMax = items.Max(p => g.MeasureString(p.Text, Font).Width);
    319                     }
    320                 }
    321                 m_rectWorking = new RectangleF(0, m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10), this.Width - fltMax, this.Height - (m_titleSize.Height == 0 ? 0 : (m_titleSize.Height + 10)));
    322             }
    323         }
    324 
    325         /// <summary>
    326         /// Resets the size of the title.
    327         /// </summary>
    328         private void ResetTitleSize()
    329         {
    330             if (string.IsNullOrEmpty(title))
    331             {
    332                 m_titleSize = SizeF.Empty;
    333             }
    334             else
    335             {
    336                 using (Graphics g = this.CreateGraphics())
    337                 {
    338                     m_titleSize = g.MeasureString(title, titleFont);
    339                     m_titleSize.Height += 20;
    340                 }
    341             }
    342             ResetWorkingRect();
    343         }
    344 
    345         /// <summary>
    346         /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
    347         /// </summary>
    348         /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" /></param>
    349         protected override void OnPaint(PaintEventArgs e)
    350         {
    351             base.OnPaint(e);
    352             var g = e.Graphics;
    353             g.SetGDIHigh();
    354 
    355             if (!string.IsNullOrEmpty(title))
    356             {
    357                 g.DrawString(title, titleFont, new SolidBrush(titleForeColor), new RectangleF(0, 0, this.Width, m_titleSize.Height), new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
    358             }
    359 
    360             if (items == null || items.Length <= 0)
    361             {
    362                 g.DrawString("没有数据", Font, new SolidBrush(Color.Black), this.m_rectWorking, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
    363                 return;
    364             }
    365 
    366             List<FunelChartItem> lstItems;
    367             if (direction == FunelChartDirection.UP)
    368             {
    369                 lstItems = items.OrderBy(p => p.Value).ToList();
    370             }
    371             else
    372             {
    373                 lstItems = items.OrderByDescending(p => p.Value).ToList();
    374             }
    375 
    376             List<RectangleF> lstRects = new List<RectangleF>();
    377             List<GraphicsPath> lstPaths = new List<GraphicsPath>();
    378             float maxValue = lstItems.Max(p => p.Value);
    379             float dblSplitHeight = m_rectWorking.Height / lstItems.Count;
    380             for (int i = 0; i < lstItems.Count; i++)
    381             {
    382                 FunelChartItem item = lstItems[i];
    383                 if (item.ValueColor == null || item.ValueColor == Color.Empty || item.ValueColor == Color.Transparent)
    384                     item.ValueColor = ControlHelper.Colors[i];
    385 
    386                 switch (alignment)
    387                 {
    388                     case FunelChartAlignment.Left:
    389                         lstRects.Add(new RectangleF(m_rectWorking.Left, m_rectWorking.Top + dblSplitHeight * i, item.Value / maxValue * m_rectWorking.Width, dblSplitHeight));
    390                         break;
    391                     case FunelChartAlignment.Center:
    392                         lstRects.Add(new RectangleF(m_rectWorking.Left + (m_rectWorking.Width - (item.Value / maxValue * m_rectWorking.Width)) / 2, m_rectWorking.Top + dblSplitHeight * i, item.Value / maxValue * m_rectWorking.Width, dblSplitHeight));
    393                         break;
    394                     case FunelChartAlignment.Right:
    395                         lstRects.Add(new RectangleF(m_rectWorking.Right - (item.Value / maxValue * m_rectWorking.Width), m_rectWorking.Top + dblSplitHeight * i, item.Value / maxValue * m_rectWorking.Width, dblSplitHeight));
    396                         break;
    397                 }
    398             }
    399 
    400             for (int i = 0; i < lstRects.Count; i++)
    401             {
    402                 var rect = lstRects[i];
    403                 GraphicsPath path = new GraphicsPath();
    404                 List<PointF> lstPoints = new List<PointF>();
    405                 if (direction == FunelChartDirection.UP)
    406                 {
    407                     switch (alignment)
    408                     {
    409                         case FunelChartAlignment.Left:
    410                             lstPoints.Add(new PointF(rect.Left, rect.Top));
    411                             if (i != 0)
    412                             {
    413                                 lstPoints.Add(new PointF(lstRects[i - 1].Right, rect.Top));
    414                             }
    415                             break;
    416                         case FunelChartAlignment.Center:
    417                             if (i == 0)
    418                             {
    419                                 lstPoints.Add(new PointF(rect.Left + rect.Width / 2, rect.Top));
    420                             }
    421                             else
    422                             {
    423                                 lstPoints.Add(new PointF(lstRects[i - 1].Left, rect.Top));
    424                                 lstPoints.Add(new PointF(lstRects[i - 1].Right, rect.Top));
    425                             }
    426                             break;
    427                         case FunelChartAlignment.Right:
    428                             if (i == 0)
    429                             {
    430                                 lstPoints.Add(new PointF(rect.Right, rect.Top));
    431                             }
    432                             else
    433                             {
    434                                 lstPoints.Add(new PointF(rect.Right - lstRects[i - 1].Width, rect.Top));
    435                                 lstPoints.Add(new PointF(rect.Right, rect.Top));
    436                             }
    437                             break;
    438                     }
    439                     lstPoints.Add(new PointF(rect.Right, rect.Bottom - intSplitWidth));
    440                     lstPoints.Add(new PointF(rect.Left, rect.Bottom - intSplitWidth));
    441                 }
    442                 else
    443                 {
    444                     lstPoints.Add(new PointF(rect.Left, rect.Top + intSplitWidth));
    445                     lstPoints.Add(new PointF(rect.Right, rect.Top + intSplitWidth));
    446                     switch (alignment)
    447                     {
    448                         case FunelChartAlignment.Left:
    449                             if (i == lstRects.Count - 1)
    450                             {
    451                                 lstPoints.Add(new PointF(rect.Left, rect.Bottom));
    452                             }
    453                             else
    454                             {
    455                                 lstPoints.Add(new PointF(lstRects[i + 1].Right, rect.Bottom));
    456                                 lstPoints.Add(new PointF(rect.Left, rect.Bottom));
    457                             }
    458                             break;
    459                         case FunelChartAlignment.Center:
    460                             if (i == lstRects.Count - 1)
    461                             {
    462                                 lstPoints.Add(new PointF(rect.Left + rect.Width / 2, rect.Bottom));
    463                             }
    464                             else
    465                             {
    466                                 lstPoints.Add(new PointF(lstRects[i + 1].Right, rect.Bottom));
    467                                 lstPoints.Add(new PointF(lstRects[i + 1].Left, rect.Bottom));
    468                             }
    469                             break;
    470                         case FunelChartAlignment.Right:
    471                             if (i == lstRects.Count - 1)
    472                             {
    473                                 lstPoints.Add(new PointF(rect.Right, rect.Bottom));
    474                             }
    475                             else
    476                             {
    477                                 lstPoints.Add(new PointF(rect.Right, rect.Bottom));
    478                                 lstPoints.Add(new PointF(lstRects[i + 1].Left, rect.Bottom));
    479                             }
    480                             break;
    481                     }
    482                 }
    483                 path.AddLines(lstPoints.ToArray());
    484                 path.CloseAllFigures();
    485                 // g.DrawPath(new Pen(new SolidBrush(lstItems[i].ValueColor.Value)), path);
    486                 g.FillPath(new SolidBrush(lstItems[i].ValueColor.Value), path);
    487 
    488                 //写字
    489                 if (itemTextAlign == FunelChartAlignment.Center)
    490                 {
    491                     g.DrawString(lstItems[i].Text + (ShowValue ? lstItems[i].Value.ToString("
    " + valueFormat) : ""), Font, new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? Color.White : lstItems[i].TextForeColor.Value), rect, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
    492                 }
    493                 else if (itemTextAlign == FunelChartAlignment.Left)
    494                 {
    495                     g.DrawString(lstItems[i].Text + (ShowValue ? lstItems[i].Value.ToString("
    " + valueFormat) : ""), Font, new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value), new RectangleF(0, rect.Top, rect.Left, rect.Height), new StringFormat() { Alignment = StringAlignment.Far, LineAlignment = StringAlignment.Center });
    496                     g.DrawLine(new Pen(new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value)), rect.Left, rect.Top + rect.Height / 2, rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
    497                 }
    498                 else
    499                 {
    500                     g.DrawString(lstItems[i].Text + (ShowValue ? lstItems[i].Value.ToString("
    " + valueFormat) : ""), Font, new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value), new RectangleF(rect.Right, rect.Top, this.Width - rect.Right, rect.Height), new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center });
    501                     g.DrawLine(new Pen(new SolidBrush((lstItems[i].TextForeColor == null || lstItems[i].TextForeColor == Color.Empty || lstItems[i].TextForeColor == Color.Transparent) ? lstItems[i].ValueColor.Value : lstItems[i].TextForeColor.Value)), rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, rect.Right, rect.Top + rect.Height / 2);
    502                 }
    503             }
    504         }
    505     }
    506 }
    View Code

    最后的话

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

  • 相关阅读:
    GXPT(一)——UI设计
    JVM系列文章(四):类载入机制
    poj 2688 状态压缩dp解tsp
    ASP.NET MVC Model绑定(四)
    cocos2dx实例开发之flappybird(入门版)
    qt creator中使用qwt插件
    [CodeEdit--Sublime]一些好用的Plugins
    NBUT 1225 NEW RDSP MODE I
    [IOC]Unity使用
    [Js/Jquery]jquery插件开发
  • 原文地址:https://www.cnblogs.com/bfyx/p/11590722.html
Copyright © 2011-2022 走看看