今天,要跟你們一塊兒分享是「GDI+動態生成流程圖」的功能。別看名字高大上(也就那樣兒--!),其實就是動態生成控件,而後GDI+繪製直線鏈接控件罷了。實際項目效果圖以下:canvas
首先,人靠衣裝馬靠鞍!在繪製流程圖以前,咱們得有個高大上的背景來陪襯,好比網格背景:api
代碼以下:微信
/// <summary> /// 初始化網格 /// </summary> private void InitGridLine() { pictureBox1.BorderStyle = BorderStyle.Fixed3D; pictureBox1.Focus(); m_picture = pictureBox1.CreateGraphics(); Bitmap canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height); Graphics gp = Graphics.FromImage(canvas); DrawGrid(gp); pictureBox1.BackgroundImage = canvas; pictureBox1.Refresh(); } //繪製網格 private void DrawGrid(Graphics gp) { for (int i = 0; i < Row; i++) { gp.DrawLine(new Pen(Color.LightCyan), (i + 1) * pictureBox1.Width / Row, 0, (i + 1) * pictureBox1.Width / Row, pictureBox1.Height); } for (int i = 0; i < colums; i++) { gp.DrawLine(new Pen(Color.LightCyan), 0, (i + 1) * pictureBox1.Height / colums, pictureBox1.Width, (i + 1) * pictureBox1.Height / colums); } }
咱們此處以PictureBox爲畫布,初始化好網格背景後,就能夠開始建立流程標籤了,效果以下:app
代碼以下:spa
/// <summary> /// 繪製元素,此處以Label爲例 /// </summary> /// <returns></returns> private Label createBlock(string lblName) { try { Label label = new Label(); label.AutoSize = false; //TODO:如需動態生成每一個標籤元素位置,請根據實際狀況,初始化標籤的Location便可。此處默認X=150,Y 以75間隔遞增 label.Location = new Point(150, iPosition); iPosition = iPosition + 75; label.Size = new Size(89, 36); label.BackColor = Color.DarkOliveGreen; label.ForeColor = Color.Black; label.FlatStyle = FlatStyle.Flat; label.TextAlign = ContentAlignment.MiddleCenter; label.Text = lblName; //TODO;能夠綁定標籤元素的右鍵事件 //label.ContextMenuStrip = contextBlock; pictureBox1.Controls.Add(label); //拖拽移動 MoveBlock(label); return label; } catch (Exception ex) { MessageBox.Show(ex.Message); } return null; }
實現動態生成的標籤拖拽移動效果,方法以下:3d
//標籤移動效果 private void MoveBlock(Label block, Label endBlock = null) { block.MouseDown += (ss, ee) => { if (ee.Button == System.Windows.Forms.MouseButtons.Left) fPoint = Control.MousePosition; }; block.MouseMove += (ss, ee) => { if (ee.Button == System.Windows.Forms.MouseButtons.Left) { Point temp = Control.MousePosition; Point res = new Point(fPoint.X - temp.X, fPoint.Y - temp.Y); block.Location = new Point(block.Location.X - res.X, block.Location.Y - res.Y); fPoint = temp; pictureBox1.Invalidate(); // <------- draw the new lines } }; }
生成好背景網格和標籤,以及實現標籤的拖拽後,就須要繪製直線按本身需求,實現鏈接了。本文咱們用 Tuple 來實現兩個標籤的鏈接關係。orm
//用於存儲須要直線鏈接的元素 List<Tuple<Label, Label>> lines = new List<Tuple<Label, Label>>();
綁定PictureBox的Paint事件,利用GDI+的DrawLine實現繪製直線。blog
private void PictureBox1_Paint(object sender, PaintEventArgs e) { foreach (Tuple<Label, Label> t in lines) { Point p1 = new Point(t.Item1.Left + t.Item1.Width / 2, t.Item1.Top + t.Item1.Height / 2); Point p2 = new Point(t.Item2.Left + t.Item2.Width / 2, t.Item2.Top + t.Item2.Height / 2); e.Graphics.DrawLine(Pens.Black, p1, p2); } }
好了,全部工做都已完成,此時,只須要把想要鏈接的兩個標籤添加到當前集合中,便可完成直線的鏈接功能。效果如圖事件
參考文獻:ip
https://docs.microsoft.com/zh-cn/dotnet/api/system.tuple-2?view=netcore-3.1
https://stackoverflow.com/questions/31626027/how-to-connect-with-line-shapes-labels-on-runtime/31642448#31642448?newreg=de162494b077460383555e4da76bdd18
因爲後續全部重寫/重繪控件都在同一個項目使用,並且Dev系統引用文件較多,壓縮後源碼文件仍然很大,若是有須要源碼的朋友,能夠微信公衆號回覆:erp,便可獲取Fucking ERP全部源碼示例~!有疑問的也能夠CALL我一塊兒探討。
最後,感謝您的耐心陪伴!若是以爲本篇博文對您或者身邊朋友有幫助的,麻煩點個關注!贈人玫瑰,手留餘香,您的支持就是我寫做最大的動力,感謝您的關注,期待和您一塊兒探討!再會!