(六十五)c#Winform自定義控制項-思維導圖/組織架構圖(工業)

来源:https://www.cnblogs.com/bfyx/archive/2019/09/11/11506080.html
-Advertisement-
Play Games

前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...


前提

入行已經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         /// 

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 標題一 標題二 ...
  • <?xml version="1.0" encoding="utf-8"?><packages> <package id="CommonServiceLocator" version="1.2" targetFramework="net452" /> <package id="Prism" vers ...
  • C# 定時器 關於C#中timer類 在C#里關於定時器類就有3個1.定義在System.Windows.Forms里2.定義在System.Threading.Timer類里3.定義在System.Timers.Timer類里System.Windows.Forms.Timer是應用於WinFor ...
  • 使用HttpClient實現http請求是非常常見的方式,有一個HttpClient的拓展類HttpClientExtensions提供了更多的拓展方法,包括但不限於 .Net 4.5之前HttpClientExtensions在System.Net.Http.dll,從.Net 4.5開始Http ...
  • 1.實現鉤子函數 鉤子(Hook)的實現需要三個主要的函數和一個委托 [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static exte ...
  • 1.企業微信登錄步驟 1.獲取企業微信Token 官方文檔:https://work.weixin.qq.com/api/doc#90000/90135/91039 2.通過Token 與前端傳的Code 參數 調用微信API獲取 訪問用戶身份 官方文檔https://work.weixin.qq. ...
  • 場景 一般在進行Winform窗體開發時都會拖拽一個Button,然後雙擊進入Button按鈕的點擊事件中,進行 點擊事件的編寫。 如果窗體上事先沒有Button按鈕,是在代碼中生成的Button按鈕,如何編寫它的點擊事件。 實現 效果 ...
  • .Net core MVC 如何使用 .NET Core,最基本的入行,很多博客以及官網都有的太多太多的例子,但是大部分沒有人做到了真的讓一個小白一步一步的去學, 我第一次接觸的時候,連最基本的wwwroot都不知道是幹嘛用的。現在我們一起來看看它是幹嘛的~ 一 什麼是.NET Core,優點如何? ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...