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 class MindMappingItemEntity
      2     {
      3         /// <summary>
      4         /// Gets or sets the identifier.
      5         /// </summary>
      6         /// <value>The identifier.</value>
      7         public string ID { get; set; }
      8         private string _text;
      9         /// <summary>
     10         /// Gets or sets the text.
     11         /// </summary>
     12         /// <value>The text.</value>
     13         public string Text
     14         {
     15             get { return _text; }
     16             set
     17             {
     18                 _text = value;
     19                 ResetSize();
     20             }
     21         }
     22         /// <summary>
     23         /// Gets or sets the data source.
     24         /// </summary>
     25         /// <value>The data source.</value>
     26         public object DataSource { get; set; }
     27         /// <summary>
     28         /// The childrens
     29         /// </summary>
     30         private MindMappingItemEntity[] _Childrens;
     31         /// <summary>
     32         /// Gets or sets the childrens.
     33         /// </summary>
     34         /// <value>The childrens.</value>
     35         public MindMappingItemEntity[] Childrens
     36         {
     37             get { return _Childrens; }
     38             set
     39             {
     40                 _Childrens = value;
     41                 if (value != null && value.Length > 0)
     42                 {
     43                     value.ToList().ForEach(p => { if (p != null) { p.ParentItem = this; } });
     44                 }
     45             }
     46         }
     47         /// <summary>
     48         /// The back color
     49         /// </summary>
     50         private Color backColor = Color.Transparent;
     51 
     52         /// <summary>
     53         /// Gets or sets the color of the back.
     54         /// </summary>
     55         /// <value>The color of the back.</value>
     56         public Color BackColor
     57         {
     58             get { return backColor; }
     59             set { backColor = value; }
     60         }
     61 
     62         private Font font = new Font("微软雅黑", 10);
     63 
     64         public Font Font
     65         {
     66             get { return font; }
     67             set
     68             {
     69                 font = value;
     70                 ResetSize();
     71             }
     72         }
     73 
     74         /// <summary>
     75         /// The fore color
     76         /// </summary>
     77         private Color foreColor = Color.Black;
     78 
     79         /// <summary>
     80         /// Gets or sets the color of the fore.
     81         /// </summary>
     82         /// <value>The color of the fore.</value>
     83         public Color ForeColor
     84         {
     85             get { return foreColor; }
     86             set { foreColor = value; }
     87         }
     88         private bool _IsExpansion = false;
     89         /// <summary>
     90         /// Gets or sets a value indicating whether the instance is expanded.
     91         /// </summary>
     92         /// <value><c>true</c> if this instance is expansion; otherwise, <c>false</c>.</value>
     93         public bool IsExpansion
     94         {
     95             get
     96             {
     97                 return _IsExpansion;
     98             }
     99             set
    100             {
    101                 if (value == _IsExpansion)
    102                     return;
    103                 _IsExpansion = value;
    104                 if (!value)
    105                 {
    106                     _Childrens.ToList().ForEach(p => { if (p != null) { p.IsExpansion = false; } });
    107                 }
    108 
    109             }
    110         }
    111 
    112         /// <summary>
    113         /// Gets the parent item.
    114         /// </summary>
    115         /// <value>The parent item.</value>
    116         public MindMappingItemEntity ParentItem { get; private set; }
    117         /// <summary>
    118         /// Gets all childrens maximum show count.
    119         /// </summary>
    120         /// <value>All childrens maximum show count.</value>
    121         public int AllChildrensMaxShowHeight { get { return GetAllChildrensMaxShowHeight(); } }
    122         /// <summary>
    123         /// Gets the maximum level.
    124         /// </summary>
    125         /// <value>The maximum level.</value>
    126         public int AllChildrensMaxShowWidth { get { return GetAllChildrensMaxShowWidth(); } }
    127 
    128         /// <summary>
    129         /// Gets all childrens maximum show count.
    130         /// </summary>
    131         /// <returns>System.Int32.</returns>
    132         private int GetAllChildrensMaxShowHeight()
    133         {
    134             if (!_IsExpansion || _Childrens == null || _Childrens.Length <= 0)
    135                 return ItemHeight + 10;
    136             else
    137             {
    138                 return _Childrens.Sum(p => p == null ? 0 : p.AllChildrensMaxShowHeight);
    139             }
    140         }
    141         /// <summary>
    142         /// Gets the maximum level.
    143         /// </summary>
    144         /// <returns>System.Int32.</returns>
    145         private int GetAllChildrensMaxShowWidth()
    146         {
    147             if (!_IsExpansion || _Childrens == null || _Childrens.Length <= 0)
    148                 return ItemWidth + 50;
    149             else
    150             {
    151                 return 1 + _Childrens.Max(p => p == null ? 0 : p.AllChildrensMaxShowWidth);
    152             }
    153         }
    154         /// <summary>
    155         /// Gets or sets the working rectangle.
    156         /// </summary>
    157         /// <value>The working rectangle.</value>
    158         internal RectangleF WorkingRectangle { get; set; }
    159         /// <summary>
    160         /// Gets or sets the draw rectangle.
    161         /// </summary>
    162         /// <value>The draw rectangle.</value>
    163         internal RectangleF DrawRectangle { get; set; }
    164         /// <summary>
    165         /// Gets or sets the expansion rectangle.
    166         /// </summary>
    167         /// <value>The expansion rectangle.</value>
    168         internal RectangleF ExpansionRectangle { get; set; }
    169         /// <summary>
    170         /// Gets the height of the item.
    171         /// </summary>
    172         /// <value>The height of the item.</value>
    173         private int ItemHeight { private get; private set; }
    174         /// <summary>
    175         /// Gets the width of the item.
    176         /// </summary>
    177         /// <value>The width of the item.</value>
    178         private int ItemWidth { private get; private set; }
    179         /// <summary>
    180         /// Resets the size.
    181         /// </summary>
    182         private void ResetSize()
    183         {
    184             string _t = _text;
    185             if (string.IsNullOrEmpty(_t))
    186             {
    187                 _t = "aaaa";
    188             }
    189             Bitmap bit = new Bitmap(1, 1);
    190             var g = Graphics.FromImage(bit);
    191             var size = g.MeasureString(_t, font);
    192             g.Dispose();
    193             bit.Dispose();
    194             ItemHeight = (int)size.Height;
    195             ItemWidth = (int)size.Width;
    196         }
    197     }

    主要属性说明:

    Text:显示文字

    Childrens:子节点信息

    BackColor:节点颜色

    IsExpansion:是否展开子节点

    ParentItem:父级节点

    AllChildrensMaxShowHeight:该节点包含所有子节点需要显示的高度,通过私有函数GetAllChildrensMaxShowHeight()返回结果

    AllChildrensMaxShowWidth:该节点包含所有子节点需要显示的宽度,通过私有函数GetAllChildrensMaxShowWidth()返回结果

    WorkingRectangle:该节点以及所有子节点的工作区域

    DrawRectangle:该节点的绘制区域

    ExpansionRectangle:展开折叠按钮的绘制区域

    ItemHeight:该节点的高度

    ItemWidth:该节点的宽度

    主要函数说明:

    GetAllChildrensMaxShowHeight:获取当前节点及所有子节点需要的最大高度

    GetAllChildrensMaxShowWidth:获取当前节点及所有子节点需要的最大宽度

    ResetSize:当文本和字体改变时重新计算宽高

    添加一个类UCMindMapping,继承UserControl

    添加一些属性

     1  /// <summary>
     2         /// The line color
     3         /// </summary>
     4         private Color lineColor = Color.Black;
     5 
     6         /// <summary>
     7         /// Gets or sets the color of the line.
     8         /// </summary>
     9         /// <value>The color of the line.</value>
    10         [Description("线条颜色"), Category("自定义")]
    11         public Color LineColor
    12         {
    13             get { return lineColor; }
    14             set
    15             {
    16                 lineColor = value;
    17                 Refresh();
    18             }
    19         }
    20         /// <summary>
    21         /// The split width
    22         /// </summary>
    23         private int splitWidth = 50;
    24         // private int itemHeight = 20;
    25         /// <summary>
    26         /// The padding
    27         /// </summary>
    28         private int padding = 20;
    29 
    30         /// <summary>
    31         /// The m rect working
    32         /// </summary>
    33         Rectangle m_rectWorking = Rectangle.Empty;
    34         /// <summary>
    35         /// Occurs when [item clicked].
    36         /// </summary>
    37         public event EventHandler ItemClicked;
    38         /// <summary>
    39         /// The data source
    40         /// </summary>
    41         private MindMappingItemEntity dataSource;
    42         /// <summary>
    43         /// Gets or sets the data source.
    44         /// </summary>
    45         /// <value>The data source.</value>
    46         [Description("数据源"), Category("自定义")]
    47         public MindMappingItemEntity DataSource
    48         {
    49             get { return dataSource; }
    50             set
    51             {
    52                 dataSource = value;
    53 
    54                 ResetSize();
    55             }
    56         }

    一个辅助函数,用以在大小过数据改变时计算工作区域和位置

     1  /// <summary>
     2         /// 重置大小
     3         /// </summary>
     4         private void ResetSize()
     5         {
     6             if (this.Parent == null)
     7                 return;
     8             try
     9             {
    10                 ControlHelper.FreezeControl(this, true);
    11                 if (dataSource == null)
    12                 {
    13                     m_rectWorking = Rectangle.Empty;
    14                     this.Size = this.Parent.Size;
    15                 }
    16                 else
    17                 {
    18                     int intWidth = dataSource.AllChildrensMaxShowWidth;
    19                     int intHeight = dataSource.AllChildrensMaxShowHeight;
    20                     this.Width = intWidth + padding * 2;
    21                     this.Height = intHeight + padding * 2;
    22                     if (this.Width < this.Parent.Width)
    23                         this.Width = this.Parent.Width;
    24                     m_rectWorking = new Rectangle(padding, padding, intWidth, intHeight);
    25                     if (this.Height > this.Parent.Height)
    26                     {
    27                         //this.Location = new Point(0, 0);
    28                     }
    29                     else
    30                         this.Location = new Point(0, (this.Parent.Height - this.Height) / 2);
    31                 }
    32             }
    33             finally
    34             {
    35                 ControlHelper.FreezeControl(this, false);
    36             }
    37         }

    重绘

     1  /// <summary>
     2         /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
     3         /// </summary>
     4         /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" /></param>
     5         protected override void OnPaint(PaintEventArgs e)
     6         {
     7             try
     8             {
     9                 base.OnPaint(e);
    10                 if (m_rectWorking == Rectangle.Empty || m_rectWorking == null)
    11                     return;
    12                 var g = e.Graphics;
    13                 g.SetGDIHigh();
    14 
    15                 int intHeight = dataSource.AllChildrensMaxShowHeight;
    16                 dataSource.WorkingRectangle = new RectangleF(m_rectWorking.Left, m_rectWorking.Top + (m_rectWorking.Height - intHeight) / 2, m_rectWorking.Width, intHeight);
    17 
    18                 DrawItem(dataSource, g);
    19             }
    20             catch (Exception exc)
    21             {
    22                 MessageBox.Show(exc.ToString(), "错误");
    23             }
    24         }
     1 /// <summary>
     2         /// 画节点
     3         /// </summary>
     4         /// <param name="item">The item.</param>
     5         /// <param name="g">The g.</param>
     6         private void DrawItem(MindMappingItemEntity item, Graphics g)
     7         {
     8             //节点
     9             var size = g.MeasureString(item.Text, item.Font);
    10             item.DrawRectangle = new RectangleF(item.WorkingRectangle.Left + 2, item.WorkingRectangle.Top + (item.WorkingRectangle.Height - size.Height) / 2 + 2, size.Width + 4, size.Height + 4);
    11             GraphicsPath drawPath = item.DrawRectangle.CreateRoundedRectanglePath(5);
    12             g.FillPath(new SolidBrush(item.BackColor), drawPath);
    13             g.DrawString(item.Text, item.Font, new SolidBrush(item.ForeColor), item.DrawRectangle.Location.X + 2, item.DrawRectangle.Location.Y + 2);
    14             //子节点
    15             if (item.Childrens != null && item.IsExpansion)
    16             {
    17                 for (int i = 0; i < item.Childrens.Length; i++)
    18                 {
    19                     var child = item.Childrens[i];
    20                     if (i == 0)
    21                     {
    22                         child.WorkingRectangle = new RectangleF(item.DrawRectangle.Right + splitWidth, item.WorkingRectangle.Top, item.WorkingRectangle.Width - (item.DrawRectangle.Width + splitWidth), child.AllChildrensMaxShowHeight);
    23                     }
    24                     else
    25                     {
    26                         child.WorkingRectangle = new RectangleF(item.DrawRectangle.Right + splitWidth, item.Childrens[i - 1].WorkingRectangle.Bottom, item.WorkingRectangle.Width - (item.DrawRectangle.Width + splitWidth), child.AllChildrensMaxShowHeight);
    27                     }
    28                     DrawItem(child, g);
    29                 }
    30             }
    31             //连线
    32             if (item.ParentItem != null)
    33             {
    34                 g.DrawLines(new Pen(new SolidBrush(lineColor), 1), new PointF[] 
    35                 { 
    36                     new PointF(item.ParentItem.DrawRectangle.Right,item.ParentItem.DrawRectangle.Top+item.ParentItem.DrawRectangle.Height/2),
    37                     new PointF(item.ParentItem.DrawRectangle.Right+12,item.ParentItem.DrawRectangle.Top+item.ParentItem.DrawRectangle.Height/2),
    38                     //new PointF(item.ParentItem.DrawRectangle.Right+12,item.DrawRectangle.Top+item.DrawRectangle.Height/2),                    
    39                     new PointF(item.DrawRectangle.Left-12,item.DrawRectangle.Top+item.DrawRectangle.Height/2),                 
    40                     new PointF(item.DrawRectangle.Left,item.DrawRectangle.Top+item.DrawRectangle.Height/2),
    41                 });
    42             }
    43             //展开折叠按钮
    44             if (item.Childrens != null && item.Childrens.Length > 0)
    45             {
    46                 RectangleF _rect = new RectangleF(item.DrawRectangle.Right + 1, item.DrawRectangle.Top + (item.DrawRectangle.Height - 10) / 2, 10, 10);
    47                 item.ExpansionRectangle = _rect;
    48                 g.FillEllipse(new SolidBrush(this.BackColor), _rect);
    49                 g.DrawEllipse(new Pen(new SolidBrush(Color.Black)), _rect);
    50                 g.DrawLine(new Pen(new SolidBrush(lineColor)), _rect.Left + 2, _rect.Y + _rect.Height / 2, _rect.Right - 2, _rect.Y + _rect.Height / 2);
    51                 if (!item.IsExpansion)
    52                 {
    53                     g.DrawLine(new Pen(new SolidBrush(lineColor)), _rect.Left + _rect.Width / 2, _rect.Top + 2, _rect.Left + _rect.Width / 2, _rect.Bottom - 2);
    54                 }
    55             }
    56         }

    控件的单击和双击时间来处理展开折叠事件

     1  /// <summary>
     2         /// 双击处理,主要用于检测节点双击展开折叠
     3         /// </summary>
     4         /// <param name="sender">The source of the event.</param>
     5         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
     6         void UCMindMapping_DoubleClick(object sender, EventArgs e)
     7         {
     8             var mouseLocation = this.PointToClient(Control.MousePosition);
     9 
    10             bool bln = CheckExpansionDoubleClick(dataSource, mouseLocation);
    11             if (bln)
    12             {
    13                 ResetSize();
    14                 this.Parent.Refresh();
    15             }
    16         }
    17 
    18         /// <summary>
    19         /// 单击处理,主要用于单击节点事件和,展开关闭圆圈处理
    20         /// </summary>
    21         /// <param name="sender">The source of the event.</param>
    22         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    23         void UCMindMapping_Click(object sender, EventArgs e)
    24         {
    25             var mouseLocation = this.PointToClient(Control.MousePosition);
    26 
    27             bool bln = CheckExpansionClick(dataSource, mouseLocation);
    28             if (bln)
    29             {
    30                 ResetSize();
    31                 this.Parent.Refresh();
    32             }
    33         }
     1   /// <summary>
     2         /// 双击检查
     3         /// </summary>
     4         /// <param name="item">The item.</param>
     5         /// <param name="mouseLocation">The mouse location.</param>
     6         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
     7         private bool CheckExpansionDoubleClick(MindMappingItemEntity item, Point mouseLocation)
     8         {
     9             if (item == null)
    10                 return false;
    11             else
    12             {
    13                 if (item.DrawRectangle.Contains(mouseLocation))
    14                 {
    15                     item.IsExpansion = !item.IsExpansion;
    16                     return true;
    17                 }
    18                 if (item.Childrens != null && item.Childrens.Length > 0)
    19                 {
    20                     foreach (var child in item.Childrens)
    21                     {
    22                         var bln = CheckExpansionDoubleClick(child, mouseLocation);
    23                         if (bln)
    24                             return bln;
    25                     }
    26                 }
    27             }
    28             return false;
    29         }
    30 
    31         /// <summary>
    32         /// 单击检查
    33         /// </summary>
    34         /// <param name="item">The item.</param>
    35         /// <param name="mouseLocation">The mouse location.</param>
    36         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
    37         private bool CheckExpansionClick(MindMappingItemEntity item, Point mouseLocation)
    38         {
    39             if (item == null)
    40                 return false;
    41             else
    42             {
    43                 if (ItemClicked != null && item.WorkingRectangle.Contains(mouseLocation))
    44                 {
    45                     ItemClicked(item, null);
    46                 }
    47                 else if (item.ExpansionRectangle.Contains(mouseLocation))
    48                 {
    49                     item.IsExpansion = !item.IsExpansion;
    50                     return true;
    51                 }
    52                 if (item.Childrens != null && item.Childrens.Length > 0)
    53                 {
    54                     foreach (var child in item.Childrens)
    55                     {
    56                         var bln = CheckExpansionClick(child, mouseLocation);
    57                         if (bln)
    58                             return bln;
    59                     }
    60                 }
    61             }
    62             return false;
    63         }

    完整代码

      1 // ***********************************************************************
      2 // Assembly         : HZH_Controls
      3 // Created          : 2019-09-11
      4 //
      5 // ***********************************************************************
      6 // <copyright file="UCMindMapping.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 UCMindMapping.
     29     /// Implements the <see cref="System.Windows.Forms.UserControl" />
     30     /// </summary>
     31     /// <seealso cref="System.Windows.Forms.UserControl" />
     32     internal class UCMindMapping : UserControl
     33     {
     34         /// <summary>
     35         /// The line color
     36         /// </summary>
     37         private Color lineColor = Color.Black;
     38 
     39         /// <summary>
     40         /// Gets or sets the color of the line.
     41         /// </summary>
     42         /// <value>The color of the line.</value>
     43         [Description("线条颜色"), Category("自定义")]
     44         public Color LineColor
     45         {
     46             get { return lineColor; }
     47             set
     48             {
     49                 lineColor = value;
     50                 Refresh();
     51             }
     52         }
     53         /// <summary>
     54         /// The split width
     55         /// </summary>
     56         private int splitWidth = 50;
     57         // private int itemHeight = 20;
     58         /// <summary>
     59         /// The padding
     60         /// </summary>
     61         private int padding = 20;
     62 
     63         /// <summary>
     64         /// The m rect working
     65         /// </summary>
     66         Rectangle m_rectWorking = Rectangle.Empty;
     67         /// <summary>
     68         /// Occurs when [item clicked].
     69         /// </summary>
     70         public event EventHandler ItemClicked;
     71         /// <summary>
     72         /// The data source
     73         /// </summary>
     74         private MindMappingItemEntity dataSource;
     75         /// <summary>
     76         /// Gets or sets the data source.
     77         /// </summary>
     78         /// <value>The data source.</value>
     79         [Description("数据源"), Category("自定义")]
     80         public MindMappingItemEntity DataSource
     81         {
     82             get { return dataSource; }
     83             set
     84             {
     85                 dataSource = value;
     86 
     87                 ResetSize();
     88             }
     89         }
     90         /// <summary>
     91         /// Initializes a new instance of the <see cref="UCMindMapping"/> class.
     92         /// </summary>
     93         public UCMindMapping()
     94         {
     95             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
     96             this.SetStyle(ControlStyles.DoubleBuffer, true);
     97             this.SetStyle(ControlStyles.ResizeRedraw, true);
     98             this.SetStyle(ControlStyles.Selectable, true);
     99             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
    100             this.SetStyle(ControlStyles.UserPaint, true);
    101             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    102             this.Click += UCMindMapping_Click;
    103             this.DoubleClick += UCMindMapping_DoubleClick;
    104             this.Load += UCMindMapping_Load;
    105         }
    106 
    107         /// <summary>
    108         /// Handles the Load event of the UCMindMapping control.
    109         /// </summary>
    110         /// <param name="sender">The source of the event.</param>
    111         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    112         void UCMindMapping_Load(object sender, EventArgs e)
    113         {
    114             if (this.Parent != null)
    115             {
    116                 //父控件大小改变时重置大小和位置
    117                 this.Parent.SizeChanged += (a, b) =>
    118                 {
    119                     ResetSize();
    120                 };
    121             }
    122         }
    123 
    124         /// <summary>
    125         /// 双击处理,主要用于检测节点双击展开折叠
    126         /// </summary>
    127         /// <param name="sender">The source of the event.</param>
    128         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    129         void UCMindMapping_DoubleClick(object sender, EventArgs e)
    130         {
    131             var mouseLocation = this.PointToClient(Control.MousePosition);
    132 
    133             bool bln = CheckExpansionDoubleClick(dataSource, mouseLocation);
    134             if (bln)
    135             {
    136                 ResetSize();
    137                 this.Parent.Refresh();
    138             }
    139         }
    140 
    141         /// <summary>
    142         /// 单击处理,主要用于单击节点事件和,展开关闭圆圈处理
    143         /// </summary>
    144         /// <param name="sender">The source of the event.</param>
    145         /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    146         void UCMindMapping_Click(object sender, EventArgs e)
    147         {
    148             var mouseLocation = this.PointToClient(Control.MousePosition);
    149 
    150             bool bln = CheckExpansionClick(dataSource, mouseLocation);
    151             if (bln)
    152             {
    153                 ResetSize();
    154                 this.Parent.Refresh();
    155             }
    156         }
    157 
    158         /// <summary>
    159         /// 双击检查
    160         /// </summary>
    161         /// <param name="item">The item.</param>
    162         /// <param name="mouseLocation">The mouse location.</param>
    163         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
    164         private bool CheckExpansionDoubleClick(MindMappingItemEntity item, Point mouseLocation)
    165         {
    166             if (item == null)
    167                 return false;
    168             else
    169             {
    170                 if (item.DrawRectangle.Contains(mouseLocation))
    171                 {
    172                     item.IsExpansion = !item.IsExpansion;
    173                     return true;
    174                 }
    175                 if (item.Childrens != null && item.Childrens.Length > 0)
    176                 {
    177                     foreach (var child in item.Childrens)
    178                     {
    179                         var bln = CheckExpansionDoubleClick(child, mouseLocation);
    180                         if (bln)
    181                             return bln;
    182                     }
    183                 }
    184             }
    185             return false;
    186         }
    187 
    188         /// <summary>
    189         /// 单击检查
    190         /// </summary>
    191         /// <param name="item">The item.</param>
    192         /// <param name="mouseLocation">The mouse location.</param>
    193         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
    194         private bool CheckExpansionClick(MindMappingItemEntity item, Point mouseLocation)
    195         {
    196             if (item == null)
    197                 return false;
    198             else
    199             {
    200                 if (ItemClicked != null && item.WorkingRectangle.Contains(mouseLocation))
    201                 {
    202                     ItemClicked(item, null);
    203                 }
    204                 else if (item.ExpansionRectangle.Contains(mouseLocation))
    205                 {
    206                     item.IsExpansion = !item.IsExpansion;
    207                     return true;
    208                 }
    209                 if (item.Childrens != null && item.Childrens.Length > 0)
    210                 {
    211                     foreach (var child in item.Childrens)
    212                     {
    213                         var bln = CheckExpansionClick(child, mouseLocation);
    214                         if (bln)
    215                             return bln;
    216                     }
    217                 }
    218             }
    219             return false;
    220         }
    221 
    222         /// <summary>
    223         /// 引发 <see cref="E:System.Windows.Forms.Control.Paint" /> 事件。
    224         /// </summary>
    225         /// <param name="e">包含事件数据的 <see cref="T:System.Windows.Forms.PaintEventArgs" /></param>
    226         protected override void OnPaint(PaintEventArgs e)
    227         {
    228             try
    229             {
    230                 base.OnPaint(e);
    231                 if (m_rectWorking == Rectangle.Empty || m_rectWorking == null)
    232                     return;
    233                 var g = e.Graphics;
    234                 g.SetGDIHigh();
    235 
    236                 int intHeight = dataSource.AllChildrensMaxShowHeight;
    237                 dataSource.WorkingRectangle = new RectangleF(m_rectWorking.Left, m_rectWorking.Top + (m_rectWorking.Height - intHeight) / 2, m_rectWorking.Width, intHeight);
    238 
    239                 DrawItem(dataSource, g);
    240             }
    241             catch (Exception exc)
    242             {
    243                 MessageBox.Show(exc.ToString(), "错误");
    244             }
    245         }
    246 
    247         /// <summary>
    248         /// 画节点
    249         /// </summary>
    250         /// <param name="item">The item.</param>
    251         /// <param name="g">The g.</param>
    252         private void DrawItem(MindMappingItemEntity item, Graphics g)
    253         {
    254             //节点
    255             var size = g.MeasureString(item.Text, item.Font);
    256             item.DrawRectangle = new RectangleF(item.WorkingRectangle.Left + 2, item.WorkingRectangle.Top + (item.WorkingRectangle.Height - size.Height) / 2 + 2, size.Width + 4, size.Height + 4);
    257             GraphicsPath drawPath = item.DrawRectangle.CreateRoundedRectanglePath(5);
    258             g.FillPath(new SolidBrush(item.BackColor), drawPath);
    259             g.DrawString(item.Text, item.Font, new SolidBrush(item.ForeColor), item.DrawRectangle.Location.X + 2, item.DrawRectangle.Location.Y + 2);
    260             //子节点
    261             if (item.Childrens != null && item.IsExpansion)
    262             {
    263                 for (int i = 0; i < item.Childrens.Length; i++)
    264                 {
    265                     var child = item.Childrens[i];
    266                     if (i == 0)
    267                     {
    268                         child.WorkingRectangle = new RectangleF(item.DrawRectangle.Right + splitWidth, item.WorkingRectangle.Top, item.WorkingRectangle.Width - (item.DrawRectangle.Width + splitWidth), child.AllChildrensMaxShowHeight);
    269                     }
    270                     else
    271                     {
    272                         child.WorkingRectangle = new RectangleF(item.DrawRectangle.Right + splitWidth, item.Childrens[i - 1].WorkingRectangle.Bottom, item.WorkingRectangle.Width - (item.DrawRectangle.Width + splitWidth), child.AllChildrensMaxShowHeight);
    273                     }
    274                     DrawItem(child, g);
    275                 }
    276             }
    277             //连线
    278             if (item.ParentItem != null)
    279             {
    280                 g.DrawLines(new Pen(new SolidBrush(lineColor), 1), new PointF[] 
    281                 { 
    282                     new PointF(item.ParentItem.DrawRectangle.Right,item.ParentItem.DrawRectangle.Top+item.ParentItem.DrawRectangle.Height/2),
    283                     new PointF(item.ParentItem.DrawRectangle.Right+12,item.ParentItem.DrawRectangle.Top+item.ParentItem.DrawRectangle.Height/2),
    284                     //new PointF(item.ParentItem.DrawRectangle.Right+12,item.DrawRectangle.Top+item.DrawRectangle.Height/2),                    
    285                     new PointF(item.DrawRectangle.Left-12,item.DrawRectangle.Top+item.DrawRectangle.Height/2),                 
    286                     new PointF(item.DrawRectangle.Left,item.DrawRectangle.Top+item.DrawRectangle.Height/2),
    287                 });
    288             }
    289             //展开折叠按钮
    290             if (item.Childrens != null && item.Childrens.Length > 0)
    291             {
    292                 RectangleF _rect = new RectangleF(item.DrawRectangle.Right + 1, item.DrawRectangle.Top + (item.DrawRectangle.Height - 10) / 2, 10, 10);
    293                 item.ExpansionRectangle = _rect;
    294                 g.FillEllipse(new SolidBrush(this.BackColor), _rect);
    295                 g.DrawEllipse(new Pen(new SolidBrush(Color.Black)), _rect);
    296                 g.DrawLine(new Pen(new SolidBrush(lineColor)), _rect.Left + 2, _rect.Y + _rect.Height / 2, _rect.Right - 2, _rect.Y + _rect.Height / 2);
    297                 if (!item.IsExpansion)
    298                 {
    299                     g.DrawLine(new Pen(new SolidBrush(lineColor)), _rect.Left + _rect.Width / 2, _rect.Top + 2, _rect.Left + _rect.Width / 2, _rect.Bottom - 2);
    300                 }
    301             }
    302         }
    303 
    304 
    305         /// <summary>
    306         /// 重置大小
    307         /// </summary>
    308         private void ResetSize()
    309         {
    310             if (this.Parent == null)
    311                 return;
    312             try
    313             {
    314                 ControlHelper.FreezeControl(this, true);
    315                 if (dataSource == null)
    316                 {
    317                     m_rectWorking = Rectangle.Empty;
    318                     this.Size = this.Parent.Size;
    319                 }
    320                 else
    321                 {
    322                     int intWidth = dataSource.AllChildrensMaxShowWidth;
    323                     int intHeight = dataSource.AllChildrensMaxShowHeight;
    324                     this.Width = intWidth + padding * 2;
    325                     this.Height = intHeight + padding * 2;
    326                     if (this.Width < this.Parent.Width)
    327                         this.Width = this.Parent.Width;
    328                     m_rectWorking = new Rectangle(padding, padding, intWidth, intHeight);
    329                     if (this.Height > this.Parent.Height)
    330                     {
    331                         //this.Location = new Point(0, 0);
    332                     }
    333                     else
    334                         this.Location = new Point(0, (this.Parent.Height - this.Height) / 2);
    335                 }
    336             }
    337             finally
    338             {
    339                 ControlHelper.FreezeControl(this, false);
    340             }
    341         }
    342     }
    343 }
    View Code

    最后再添加一个父控件,来包裹该控件,用以可以有滚动条的处理

    添加一个用户控件UCMindMappingPanel,控件上添加一个上面新增的ucMindMapping,

    完整代码

      1 // ***********************************************************************
      2 // Assembly         : HZH_Controls
      3 // Created          : 2019-09-11
      4 //
      5 // ***********************************************************************
      6 // <copyright file="UCMindMappingPanel.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.ComponentModel;
     19 using System.Drawing;
     20 using System.Data;
     21 using System.Linq;
     22 using System.Text;
     23 using System.Windows.Forms;
     24 
     25 namespace HZH_Controls.Controls
     26 {
     27     /// <summary>
     28     /// Class UCMindMappingPanel.
     29     /// Implements the <see cref="System.Windows.Forms.UserControl" />
     30     /// </summary>
     31     /// <seealso cref="System.Windows.Forms.UserControl" />
     32     public partial class UCMindMappingPanel : UserControl
     33     {
     34         /// <summary>
     35         /// The data source
     36         /// </summary>
     37         private MindMappingItemEntity dataSource;
     38 
     39         /// <summary>
     40         /// Gets or sets the data source.
     41         /// </summary>
     42         /// <value>The data source.</value>
     43         [Description("数据源"), Category("自定义")]
     44         public MindMappingItemEntity DataSource
     45         {
     46             get { return dataSource; }
     47             set
     48             {
     49                 dataSource = value;
     50                 this.ucMindMapping1.DataSource = value;
     51             }
     52         }
     53         /// <summary>
     54         /// Gets or sets the data source.
     55         /// </summary>
     56         /// <value>The data source.</value>
     57         [Description("数据源"), Category("自定义")]
     58         public event EventHandler ItemClicked;
     59 
     60         /// <summary>
     61         /// The line color
     62         /// </summary>
     63         private Color lineColor = Color.Black;
     64 
     65         /// <summary>
     66         /// Gets or sets the color of the line.
     67         /// </summary>
     68         /// <value>The color of the line.</value>
     69         [Description("线条颜色"), Category("自定义")]
     70         public Color LineColor
     71         {
     72             get { return lineColor; }
     73             set
     74             {
     75                 lineColor = value;
     76                 this.ucMindMapping1.LineColor = value;
     77             }
     78         }
     79         /// <summary>
     80         /// Initializes a new instance of the <see cref="UCMindMappingPanel"/> class.
     81         /// </summary>
     82         public UCMindMappingPanel()
     83         {
     84             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
     85             this.SetStyle(ControlStyles.DoubleBuffer, true);
     86             this.SetStyle(ControlStyles.ResizeRedraw, true);
     87             this.SetStyle(ControlStyles.Selectable, true);
     88             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
     89             this.SetStyle(ControlStyles.UserPaint, true);
     90             InitializeComponent();
     91             ucMindMapping1.ItemClicked += ucMindMapping1_ItemClicked;
     92         }
     93 
     94         void ucMindMapping1_ItemClicked(object sender, EventArgs e)
     95         {
     96             if (ItemClicked != null)
     97             {
     98                 ItemClicked(sender, e);
     99             }
    100         }
    101     }
    102 }
     1 namespace HZH_Controls.Controls
     2 {
     3     partial class UCMindMappingPanel
     4     {
     5         /// <summary> 
     6         /// 必需的设计器变量。
     7         /// </summary>
     8         private System.ComponentModel.IContainer components = null;
     9 
    10         /// <summary> 
    11         /// 清理所有正在使用的资源。
    12         /// </summary>
    13         /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
    14         protected override void Dispose(bool disposing)
    15         {
    16             if (disposing && (components != null))
    17             {
    18                 components.Dispose();
    19             }
    20             base.Dispose(disposing);
    21         }
    22 
    23         #region 组件设计器生成的代码
    24 
    25         /// <summary> 
    26         /// 设计器支持所需的方法 - 不要
    27         /// 使用代码编辑器修改此方法的内容。
    28         /// </summary>
    29         private void InitializeComponent()
    30         {
    31             this.ucMindMapping1 = new HZH_Controls.Controls.UCMindMapping();
    32             this.SuspendLayout();
    33             // 
    34             // ucMindMapping1
    35             // 
    36             this.ucMindMapping1.Location = new System.Drawing.Point(0, 0);
    37             this.ucMindMapping1.Name = "ucMindMapping1";
    38             this.ucMindMapping1.Size = new System.Drawing.Size(200, 200);
    39             this.ucMindMapping1.TabIndex = 0;
    40             // 
    41             // UCMindMappingPanel
    42             // 
    43             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
    44             this.AutoScroll = true;
    45             this.BackColor = System.Drawing.Color.White;
    46             this.Controls.Add(this.ucMindMapping1);
    47             this.Name = "UCMindMappingPanel";
    48             this.Size = new System.Drawing.Size(200, 200);
    49             this.ResumeLayout(false);
    50 
    51         }
    52 
    53         #endregion
    54 
    55         private UCMindMapping ucMindMapping1;
    56     }
    57 }
    View Code

    最后的话

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

  • 相关阅读:
    Invalid bound statement (not found)解决方法
    MySQL的sum()函数
    关于Mybatis的java.lang.UnsupportedOperationException异常处理
    博客迁移
    Building Blog(个性化博客)2
    走一波服务器
    JZ高中OJ 1036. [SCOI2009]迷路
    JZ初中OJ 2296. [noip普及组2]神殿
    JZ初中OJ 2295. [noip普及组2]栈
    JZ初中OJ 2298. [noip普及组2]异或
  • 原文地址:https://www.cnblogs.com/bfyx/p/11506080.html
Copyright © 2011-2022 走看看