(六十五)c#Winform自定义控件-思维导图/组织架构图(工业)

前提

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

GitHub:https://github.com/kwwwvagaa/NetWinformControl

码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

如果觉得写的还行,请点个 star 支持一下吧

欢迎前来交流探讨: 企鹅群568015492 企鹅群568015492

麻烦博客下方点个【推荐】,谢谢

NuGet

Install-Package HZH_Controls

目录

https://blog.csdn.net/kwwwvagaa/article/details/100586547

用处及效果

(六十五)c#Winform自定义控件-思维导图/组织架构图(工业)_第1张图片

准备工作

依然是用GDI+画的,不懂的可以先百度一下

开始

添加一个实体类,用以记录数据源节点信息

复制代码

  1  public class MindMappingItemEntity
  2     {
  3         /// 
  4         /// Gets or sets the identifier.
  5         /// 
  6         /// The identifier.
  7         public string ID { get; set; }
  8         private string _text;
  9         /// 
 10         /// Gets or sets the text.
 11         /// 
 12         /// The text.
 13         public string Text
 14         {
 15             get { return _text; }
 16             set
 17             {
 18                 _text = value;
 19                 ResetSize();
 20             }
 21         }
 22         /// 
 23         /// Gets or sets the data source.
 24         /// 
 25         /// The data source.
 26         public object DataSource { get; set; }
 27         /// 
 28         /// The childrens
 29         /// 
 30         private MindMappingItemEntity[] _Childrens;
 31         /// 
 32         /// Gets or sets the childrens.
 33         /// 
 34         /// The childrens.
 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         /// 
 48         /// The back color
 49         /// 
 50         private Color backColor = Color.Transparent;
 51 
 52         /// 
 53         /// Gets or sets the color of the back.
 54         /// 
 55         /// The color of the back.
 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         /// 
 75         /// The fore color
 76         /// 
 77         private Color foreColor = Color.Black;
 78 
 79         /// 
 80         /// Gets or sets the color of the fore.
 81         /// 
 82         /// The color of the fore.
 83         public Color ForeColor
 84         {
 85             get { return foreColor; }
 86             set { foreColor = value; }
 87         }
 88         private bool _IsExpansion = false;
 89         /// 
 90         /// Gets or sets a value indicating whether the instance is expanded.
 91         /// 
 92         /// true if this instance is expansion; otherwise, false.
 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         /// 
113         /// Gets the parent item.
114         /// 
115         /// The parent item.
116         public MindMappingItemEntity ParentItem { get; private set; }
117         /// 
118         /// Gets all childrens maximum show count.
119         /// 
120         /// All childrens maximum show count.
121         public int AllChildrensMaxShowHeight { get { return GetAllChildrensMaxShowHeight(); } }
122         /// 
123         /// Gets the maximum level.
124         /// 
125         /// The maximum level.
126         public int AllChildrensMaxShowWidth { get { return GetAllChildrensMaxShowWidth(); } }
127 
128         /// 
129         /// Gets all childrens maximum show count.
130         /// 
131         /// System.Int32.
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         /// 
142         /// Gets the maximum level.
143         /// 
144         /// System.Int32.
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         /// 
155         /// Gets or sets the working rectangle.
156         /// 
157         /// The working rectangle.
158         internal RectangleF WorkingRectangle { get; set; }
159         /// 
160         /// Gets or sets the draw rectangle.
161         /// 
162         /// The draw rectangle.
163         internal RectangleF DrawRectangle { get; set; }
164         /// 
165         /// Gets or sets the expansion rectangle.
166         /// 
167         /// The expansion rectangle.
168         internal RectangleF ExpansionRectangle { get; set; }
169         /// 
170         /// Gets the height of the item.
171         /// 
172         /// The height of the item.
173         private int ItemHeight { private get; private set; }
174         /// 
175         /// Gets the width of the item.
176         /// 
177         /// The width of the item.
178         private int ItemWidth { private get; private set; }
179         /// 
180         /// Resets the size.
181         /// 
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  /// 
 2         /// The line color
 3         /// 
 4         private Color lineColor = Color.Black;
 5 
 6         /// 
 7         /// Gets or sets the color of the line.
 8         /// 
 9         /// The color of the line.
10         [Description("线条颜色"), Category("自定义")]
11         public Color LineColor
12         {
13             get { return lineColor; }
14             set
15             {
16                 lineColor = value;
17                 Refresh();
18             }
19         }
20         /// 
21         /// The split width
22         /// 
23         private int splitWidth = 50;
24         // private int itemHeight = 20;
25         /// 
26         /// The padding
27         /// 
28         private int padding = 20;
29 
30         /// 
31         /// The m rect working
32         /// 
33         Rectangle m_rectWorking = Rectangle.Empty;
34         /// 
35         /// Occurs when [item clicked].
36         /// 
37         public event EventHandler ItemClicked;
38         /// 
39         /// The data source
40         /// 
41         private MindMappingItemEntity dataSource;
42         /// 
43         /// Gets or sets the data source.
44         /// 
45         /// The data source.
46         [Description("数据源"), Category("自定义")]
47         public MindMappingItemEntity DataSource
48         {
49             get { return dataSource; }
50             set
51             {
52                 dataSource = value;
53 
54                 ResetSize();
55             }
56         }

复制代码

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

复制代码

 1  /// 
 2         /// 重置大小
 3         /// 
 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  /// 
 2         /// 引发  事件。
 3         /// 
 4         /// 包含事件数据的 。
 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 /// 
 2         /// 画节点
 3         /// 
 4         /// The item.
 5         /// The g.
 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  /// 
 2         /// 双击处理,主要用于检测节点双击展开折叠
 3         /// 
 4         /// The source of the event.
 5         /// The  instance containing the event data.
 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         /// 
19         /// 单击处理,主要用于单击节点事件和,展开关闭圆圈处理
20         /// 
21         /// The source of the event.
22         /// The  instance containing the event data.
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   /// 
 2         /// 双击检查
 3         /// 
 4         /// The item.
 5         /// The mouse location.
 6         /// true if XXXX, false otherwise.
 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         /// 
32         /// 单击检查
33         /// 
34         /// The item.
35         /// The mouse location.
36         /// true if XXXX, false otherwise.
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         }

复制代码

完整代码

// ***********************************************************************
// Assembly         : HZH_Controls
// Created          : 2019-09-11
//
// ***********************************************************************
// 
//     Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:[email protected]
// 
//
// Blog: https://www.cnblogs.com/bfyx
// GitHub:https://github.com/kwwwvagaa/NetWinformControl
// gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// If you use this code, please keep this note.
// ***********************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.ComponentModel;

namespace HZH_Controls.Controls
{
    /// 
    /// Class UCMindMapping.
    /// Implements the 
    /// 
    /// 
    internal class UCMindMapping : UserControl
    {
        /// 
        /// The line color
        /// 
        private Color lineColor = Color.Black;

        /// 
        /// Gets or sets the color of the line.
        /// 
        /// The color of the line.
        [Description("线条颜色"), Category("自定义")]
        public Color LineColor
        {
            get { return lineColor; }
            set
            {
                lineColor = value;
                Refresh();
            }
        }
        /// 
        /// The split width
        /// 
        private int splitWidth = 50;
        // private int itemHeight = 20;
        /// 
        /// The padding
        /// 
        private int padding = 20;

        /// 
        /// The m rect working
        /// 
        Rectangle m_rectWorking = Rectangle.Empty;
        /// 
        /// Occurs when [item clicked].
        /// 
        public event EventHandler ItemClicked;
        /// 
        /// The data source
        /// 
        private MindMappingItemEntity dataSource;
        /// 
        /// Gets or sets the data source.
        /// 
        /// The data source.
        [Description("数据源"), Category("自定义")]
        public MindMappingItemEntity DataSource
        {
            get { return dataSource; }
            set
            {
                dataSource = value;

                ResetSize();
            }
        }
        /// 
        /// Initializes a new instance of the  class.
        /// 
        public UCMindMapping()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
            this.Click += UCMindMapping_Click;
            this.DoubleClick += UCMindMapping_DoubleClick;
            this.Load += UCMindMapping_Load;
        }

        /// 
        /// Handles the Load event of the UCMindMapping control.
        /// 
        /// The source of the event.
        /// The  instance containing the event data.
        void UCMindMapping_Load(object sender, EventArgs e)
        {
            if (this.Parent != null)
            {
                //父控件大小改变时重置大小和位置
                this.Parent.SizeChanged += (a, b) =>
                {
                    ResetSize();
                };
            }
        }

        /// 
        /// 双击处理,主要用于检测节点双击展开折叠
        /// 
        /// The source of the event.
        /// The  instance containing the event data.
        void UCMindMapping_DoubleClick(object sender, EventArgs e)
        {
            var mouseLocation = this.PointToClient(Control.MousePosition);

            bool bln = CheckExpansionDoubleClick(dataSource, mouseLocation);
            if (bln)
            {
                ResetSize();
                this.Parent.Refresh();
            }
        }

        /// 
        /// 单击处理,主要用于单击节点事件和,展开关闭圆圈处理
        /// 
        /// The source of the event.
        /// The  instance containing the event data.
        void UCMindMapping_Click(object sender, EventArgs e)
        {
            var mouseLocation = this.PointToClient(Control.MousePosition);

            bool bln = CheckExpansionClick(dataSource, mouseLocation);
            if (bln)
            {
                ResetSize();
                this.Parent.Refresh();
            }
        }

        /// 
        /// 双击检查
        /// 
        /// The item.
        /// The mouse location.
        /// true if XXXX, false otherwise.
        private bool CheckExpansionDoubleClick(MindMappingItemEntity item, Point mouseLocation)
        {
            if (item == null)
                return false;
            else
            {
                if (item.DrawRectangle.Contains(mouseLocation))
                {
                    item.IsExpansion = !item.IsExpansion;
                    return true;
                }
                if (item.Childrens != null && item.Childrens.Length > 0)
                {
                    foreach (var child in item.Childrens)
                    {
                        var bln = CheckExpansionDoubleClick(child, mouseLocation);
                        if (bln)
                            return bln;
                    }
                }
            }
            return false;
        }

        /// 
        /// 单击检查
        /// 
        /// The item.
        /// The mouse location.
        /// true if XXXX, false otherwise.
        private bool CheckExpansionClick(MindMappingItemEntity item, Point mouseLocation)
        {
            if (item == null)
                return false;
            else
            {
                if (ItemClicked != null && item.WorkingRectangle.Contains(mouseLocation))
                {
                    ItemClicked(item, null);
                }
                else if (item.ExpansionRectangle.Contains(mouseLocation))
                {
                    item.IsExpansion = !item.IsExpansion;
                    return true;
                }
                if (item.Childrens != null && item.Childrens.Length > 0)
                {
                    foreach (var child in item.Childrens)
                    {
                        var bln = CheckExpansionClick(child, mouseLocation);
                        if (bln)
                            return bln;
                    }
                }
            }
            return false;
        }

        /// 
        /// 引发  事件。
        /// 
        /// 包含事件数据的 。
        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                base.OnPaint(e);
                if (m_rectWorking == Rectangle.Empty || m_rectWorking == null)
                    return;
                var g = e.Graphics;
                g.SetGDIHigh();

                int intHeight = dataSource.AllChildrensMaxShowHeight;
                dataSource.WorkingRectangle = new RectangleF(m_rectWorking.Left, m_rectWorking.Top + (m_rectWorking.Height - intHeight) / 2, m_rectWorking.Width, intHeight);

                DrawItem(dataSource, g);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString(), "错误");
            }
        }

        /// 
        /// 画节点
        /// 
        /// The item.
        /// The g.
        private void DrawItem(MindMappingItemEntity item, Graphics g)
        {
            //节点
            var size = g.MeasureString(item.Text, item.Font);
            item.DrawRectangle = new RectangleF(item.WorkingRectangle.Left + 2, item.WorkingRectangle.Top + (item.WorkingRectangle.Height - size.Height) / 2 + 2, size.Width + 4, size.Height + 4);
            GraphicsPath drawPath = item.DrawRectangle.CreateRoundedRectanglePath(5);
            g.FillPath(new SolidBrush(item.BackColor), drawPath);
            g.DrawString(item.Text, item.Font, new SolidBrush(item.ForeColor), item.DrawRectangle.Location.X + 2, item.DrawRectangle.Location.Y + 2);
            //子节点
            if (item.Childrens != null && item.IsExpansion)
            {
                for (int i = 0; i < item.Childrens.Length; i++)
                {
                    var child = item.Childrens[i];
                    if (i == 0)
                    {
                        child.WorkingRectangle = new RectangleF(item.DrawRectangle.Right + splitWidth, item.WorkingRectangle.Top, item.WorkingRectangle.Width - (item.DrawRectangle.Width + splitWidth), child.AllChildrensMaxShowHeight);
                    }
                    else
                    {
                        child.WorkingRectangle = new RectangleF(item.DrawRectangle.Right + splitWidth, item.Childrens[i - 1].WorkingRectangle.Bottom, item.WorkingRectangle.Width - (item.DrawRectangle.Width + splitWidth), child.AllChildrensMaxShowHeight);
                    }
                    DrawItem(child, g);
                }
            }
            //连线
            if (item.ParentItem != null)
            {
                g.DrawLines(new Pen(new SolidBrush(lineColor), 1), new PointF[] 
                { 
                    new PointF(item.ParentItem.DrawRectangle.Right,item.ParentItem.DrawRectangle.Top+item.ParentItem.DrawRectangle.Height/2),
                    new PointF(item.ParentItem.DrawRectangle.Right+12,item.ParentItem.DrawRectangle.Top+item.ParentItem.DrawRectangle.Height/2),
                    //new PointF(item.ParentItem.DrawRectangle.Right+12,item.DrawRectangle.Top+item.DrawRectangle.Height/2),                    
                    new PointF(item.DrawRectangle.Left-12,item.DrawRectangle.Top+item.DrawRectangle.Height/2),                 
                    new PointF(item.DrawRectangle.Left,item.DrawRectangle.Top+item.DrawRectangle.Height/2),
                });
            }
            //展开折叠按钮
            if (item.Childrens != null && item.Childrens.Length > 0)
            {
                RectangleF _rect = new RectangleF(item.DrawRectangle.Right + 1, item.DrawRectangle.Top + (item.DrawRectangle.Height - 10) / 2, 10, 10);
                item.ExpansionRectangle = _rect;
                g.FillEllipse(new SolidBrush(this.BackColor), _rect);
                g.DrawEllipse(new Pen(new SolidBrush(Color.Black)), _rect);
                g.DrawLine(new Pen(new SolidBrush(lineColor)), _rect.Left + 2, _rect.Y + _rect.Height / 2, _rect.Right - 2, _rect.Y + _rect.Height / 2);
                if (!item.IsExpansion)
                {
                    g.DrawLine(new Pen(new SolidBrush(lineColor)), _rect.Left + _rect.Width / 2, _rect.Top + 2, _rect.Left + _rect.Width / 2, _rect.Bottom - 2);
                }
            }
        }


        /// 
        /// 重置大小
        /// 
        private void ResetSize()
        {
            if (this.Parent == null)
                return;
            try
            {
                ControlHelper.FreezeControl(this, true);
                if (dataSource == null)
                {
                    m_rectWorking = Rectangle.Empty;
                    this.Size = this.Parent.Size;
                }
                else
                {
                    int intWidth = dataSource.AllChildrensMaxShowWidth;
                    int intHeight = dataSource.AllChildrensMaxShowHeight;
                    this.Width = intWidth + padding * 2;
                    this.Height = intHeight + padding * 2;
                    if (this.Width < this.Parent.Width)
                        this.Width = this.Parent.Width;
                    m_rectWorking = new Rectangle(padding, padding, intWidth, intHeight);
                    if (this.Height > this.Parent.Height)
                    {
                        //this.Location = new Point(0, 0);
                    }
                    else
                        this.Location = new Point(0, (this.Parent.Height - this.Height) / 2);
                }
            }
            finally
            {
                ControlHelper.FreezeControl(this, false);
            }
        }
    }
}

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

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

完整代码

复制代码

  1 // ***********************************************************************
  2 // Assembly         : HZH_Controls
  3 // Created          : 2019-09-11
  4 //
  5 // ***********************************************************************
  6 // 
  7 //     Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:[email protected]
  8 // 
  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     /// 
 28     /// Class UCMindMappingPanel.
 29     /// Implements the 
 30     /// 
 31     /// 
 32     public partial class UCMindMappingPanel : UserControl
 33     {
 34         /// 
 35         /// The data source
 36         /// 
 37         private MindMappingItemEntity dataSource;
 38 
 39         /// 
 40         /// Gets or sets the data source.
 41         /// 
 42         /// The data source.
 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         /// 
 54         /// Gets or sets the data source.
 55         /// 
 56         /// The data source.
 57         [Description("数据源"), Category("自定义")]
 58         public event EventHandler ItemClicked;
 59 
 60         /// 
 61         /// The line color
 62         /// 
 63         private Color lineColor = Color.Black;
 64 
 65         /// 
 66         /// Gets or sets the color of the line.
 67         /// 
 68         /// The color of the line.
 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         /// 
 80         /// Initializes a new instance of the  class.
 81         /// 
 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 }

复制代码

namespace HZH_Controls.Controls
{
    partial class UCMindMappingPanel
    {
        ///  
        /// 必需的设计器变量。
        /// 
        private System.ComponentModel.IContainer components = null;

        ///  
        /// 清理所有正在使用的资源。
        /// 
        /// 如果应释放托管资源,为 true;否则为 false。
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region 组件设计器生成的代码

        ///  
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// 
        private void InitializeComponent()
        {
            this.ucMindMapping1 = new HZH_Controls.Controls.UCMindMapping();
            this.SuspendLayout();
            // 
            // ucMindMapping1
            // 
            this.ucMindMapping1.Location = new System.Drawing.Point(0, 0);
            this.ucMindMapping1.Name = "ucMindMapping1";
            this.ucMindMapping1.Size = new System.Drawing.Size(200, 200);
            this.ucMindMapping1.TabIndex = 0;
            // 
            // UCMindMappingPanel
            // 
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
            this.AutoScroll = true;
            this.BackColor = System.Drawing.Color.White;
            this.Controls.Add(this.ucMindMapping1);
            this.Name = "UCMindMappingPanel";
            this.Size = new System.Drawing.Size(200, 200);
            this.ResumeLayout(false);

        }

        #endregion

        private UCMindMapping ucMindMapping1;
    }
}

最后的话

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

你可能感兴趣的:(自定义控件)