<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [原創]《C#高級GDI+實戰:從零開發一個流程圖》第03章:畫一個線,連接兩個矩形!

      一、前言

      上一節我們實現了多個不同顏色的可拖動的矩形,那么這一節就來看一下如何將這些矩形連起來吧。

      相信看完的你,一定會有所收獲!

      本文地址:http://www.rzrgm.cn/lesliexin/p/18923105

      二、先看效果

      同樣的,我們先來看一下本節所實現的效果,先有一個整體的印象。

      通過視頻我們可以看到,我們本節仍是分為三個步驟依次遞進:

      在兩個矩形中添加一條直線,連接兩個形狀的中心
      在【任意】兩個矩形之間添加一條直線
      在任意兩個矩形之間添加【不同顏色】直線,連線去重,中止添加連線操作

      下面我們就來依次講解。

      對了,這里說明一下,從本節課程開始,因為后續的課程都是在前一節課程的基礎上實現的,所以原理圖中會著重標識出來(一般使用綠色)這些新的點,同時代碼實操部分僅會講解對應的這部分代碼。因為之前都已講過,每次都從零講篇幅會越來越長而且容易產生混亂。當然了,雖然僅講重點,但是全部的代碼時會貼到每小節最后的,大家可以自行查看和編譯。

      三、實現效果1:在兩個矩形中添加一條直線

      我們先來實現最簡單的情況:在兩個矩形中添加一條直線

      (一)原理

      原理很簡單,在繪制矩形后,取兩個矩形的中心點,然后繪制一條直線即可。

      原理圖如下,注意圖中的綠色元素就是與上節課原理圖的差異之處。

      image

      順便說一句:本文所有的原理圖都是使用《LN流程圖》制作的,而這也正是本系列課程最終的實現效果,相當于自產自銷了是。

      (二)代碼實操

      1,設計器界面

      設計器界面沒什么大的變化:

      image

      2,添加連線代碼

      我們看下原理圖中的綠色形狀,我們要添加一條直線,以連接兩個矩形的中心點。

      那么首先就是計算兩個矩形的中心點坐標到兩個全局變量:

      image

      之后就在繪制矩形后,添加上繪制連線的方法:

      image

      3,鼠標移動事件

      我們再來看下原理圖中的另一個綠色形狀說明,我們要在鼠標移動時,重新計算連線兩點的坐標,并進行重繪,所以我們需要在MouseMove事件中添加計算兩點坐標的方法。

      image

      好了,到此我們依照原理圖對代碼改造完畢,也就可以實現視頻的效果1了。

      下面有完整的代碼,大家嘗試一下吧。

      點擊查看代碼
      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows.Forms;
      
      namespace FlowChartDemo
      {
          public partial class FormDemo02V1 : FormBase
          {
              public FormDemo02V1()
              {
                  InitializeComponent();
                  DemoTitle = "第03節隨課Demo  Part1";
                  DemoNote = "效果:在兩個矩形中添加【一條】直線,連接兩個形狀的中心";
              }
      
              /// <summary>
              /// 矩形定義
              /// </summary>
              public class RectShape
              {
                  /// <summary>
                  /// 矩形ID
                  /// </summary>
                  public string Id { get; set; }
                  /// <summary>
                  /// 矩形位置和尺寸
                  /// </summary>
                  public Rectangle Rect { get; set; }
              }
      
              /// <summary>
              /// 當前界面矩形集合
              /// </summary>
              List<RectShape> Shapes = new List<RectShape>();
      
              /// <summary>
              /// 畫一個矩形(不同顏色)
              /// </summary>
              /// <param name="g"></param>
              /// <param name="shape"></param>
              void DrawShape2(Graphics g, RectShape shape)
              {
                  var index = Shapes.FindIndex(a => a.Id == shape.Id);
                  g.FillRectangle(GetBrush(index), shape.Rect);
                  g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
              }
      
              /// <summary>
              /// 重新繪制當前所有矩形和連線
              /// </summary>
              /// <param name="g"></param>
              void DrawAll(Graphics g)
              {
                  g.Clear(panel1.BackColor) ;
                  foreach (var sp in Shapes)
                  {
                      DrawShape2(g, sp);
                  }
      
                  if (!LinePointStart.IsEmpty&& !LinePointEnd.IsEmpty)
                  {
                      //如果連線兩個端點不是空的,則繪制連線
                      g.DrawLine(Pens.Black, LinePointStart, LinePointEnd);
                  }
              }
      
              /// <summary>
              /// 當前是否有鼠標按下,且有矩形被選中
              /// </summary>
              bool _isMouseDown = false;
              /// <summary>
              /// 最后一次鼠標的位置
              /// </summary>
              Point _lastMouseLocation = Point.Empty;
              /// <summary>
              /// 當前被鼠標選中的矩形
              /// </summary>
              RectShape _selectedShape = null;
              /// <summary>
              /// 連線起點
              /// </summary>
              Point LinePointStart = Point.Empty;
              /// <summary>
              /// 連線終點
              /// </summary>
              Point LinePointEnd = Point.Empty;
      
              /// <summary>
              /// 獲取不同的背景顏色
              /// </summary>
              /// <param name="i"></param>
              /// <returns></returns>
              Brush GetBrush(int i)
              {
                  switch (i)
                  {
                      case 0: return Brushes.Red;
                      case 1: return Brushes.Green;
                      case 2: return Brushes.Blue;
                      case 3: return Brushes.Orange;
                      case 4: return Brushes.Purple;
                      default: return Brushes.Red;
                  }
              }
      
              /// <summary>
              /// 計算并生成連線的兩個連接點
              /// </summary>
              void CreateLinePoint()
              {
      
                  //計算連線開始點坐標
                  var line1X = Shapes[0].Rect.X + Shapes[0].Rect.Width / 2;
                  var line1Y = Shapes[0].Rect.Y + Shapes[0].Rect.Height / 2;
                  LinePointStart = new Point(line1X, line1Y);
      
                  //計算連線結束點坐標
                  var line2X = Shapes[1].Rect.X + Shapes[1].Rect.Width / 2;
                  var line2Y = Shapes[1].Rect.Y + Shapes[1].Rect.Height / 2;
                  LinePointEnd = new Point(line2X, line2Y);
              }
      
              private void toolStripButton1_Click(object sender, EventArgs e)
              {
                  //此處僅顯示兩個形狀
                  if (Shapes.Count != 0)
                  {
                      MessageBox.Show("形狀已添加,不可重復操作!");
                      return;
                  }
                  
                  //添加2個矩形
                  var rs = new RectShape()
                  {
                      Id = "矩形" + (Shapes.Count + 1),
                      Rect = new Rectangle()
                      {
                          X = 50,
                          Y = 50,
                          Width = 100,
                          Height = 100,
                      },
                  };
                  Shapes.Add(rs);
                  rs = new RectShape()
                  {
                      Id = "矩形" + (Shapes.Count + 1),
                      Rect = new Rectangle()
                      {
                          X = 50,
                          Y = 50,
                          Width = 100,
                          Height = 100,
                      },
                  };
                  Shapes.Add(rs);
      
                  //生成連線的兩個連接點
                  CreateLinePoint();
      
                  //重繪所有矩形
                  DrawAll(panel1.CreateGraphics());
              }
      
              private void panel1_MouseDown(object sender, MouseEventArgs e)
              {
                  //當鼠標按下時
      
                  //取最上方的矩形,也就是最后添加的矩形
                  var sp = Shapes.FindLast(a => a.Rect.Contains(e.Location));
                  if (sp != null)
                  {
                      //證明取到了矩形
      
                      //設置狀態及選中矩形
                      _isMouseDown = true;
                      _lastMouseLocation = e.Location;
                      _selectedShape = sp;
                  }
              }
      
              private void panel1_MouseMove(object sender, MouseEventArgs e)
              {
                  //當鼠標移動時
      
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //改變選中矩形的位置信息,隨著鼠標移動而移動
      
                      //計算鼠標位置變化信息
                      var moveX = e.Location.X - _lastMouseLocation.X;
                      var moveY = e.Location.Y - _lastMouseLocation.Y;
      
                      //將選中形狀的位置進行同樣的變化
                      var oldXY = _selectedShape.Rect.Location;
                      oldXY.Offset(moveX, moveY);
                      _selectedShape.Rect = new Rectangle(oldXY, _selectedShape.Rect.Size);
      
                      //記錄當前鼠標位置
                      _lastMouseLocation.Offset(moveX, moveY);
      
                      //因為形狀位置發生了變化,所以要重新計算連線的兩個連接點
                      CreateLinePoint();
      
                      //重繪所有矩形
                      DrawAll(panel1.CreateGraphics());
                  }
      
              }
      
              private void panel1_MouseUp(object sender, MouseEventArgs e)
              {
                  //當鼠標松開時
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //重置相關記錄信息
                      _isMouseDown = false;
                      _lastMouseLocation = Point.Empty;
                      _selectedShape = null;
                  }
              }
      
          }
      
      
      }
      
      

      四、實現效果2:任意兩個矩形之間添加一條直線

      我們下面實現效果2,這個改動就比較多了,我們下面一點點講解。

      (一)原理

      同樣的,我們先來看原理圖,這個原理圖是在上面小節原理圖上增加了新的節點,并使用綠色進行了著重標注。

      image

      可以看到,增加的節點流程還是挺多的,大家可以嘗試先自行讀一下原理圖,有一個整體的印象,好看下面的實操部分。

      (二)代碼實操

      1,設計器界面

      因為要在任意兩個矩形之間添加一條直線,所以就需要有一個連線狀態控制及提示,所以界面也有了些改動:

      image

      2,進入連線狀態

      我們要在任意兩個矩形之間添加直線,肯定要依次選擇兩個矩形,這就需要有個“連線狀態”,以標識我們現在點擊矩形是為了添加連線,而不是移動矩形什么的。

      我們用一個按鈕和變量來控制,點擊按鈕后,設置變量,以標識現在進入了連線狀態,并設置提示信息“請點擊第1個矩形”:

      image

      image

      3,鼠標點擊事件

      我們通過原理圖可以看到,變化最大地方就是這個MouseDown事件,在這個事件中,我們要額外判斷是否處理連線狀態,并判斷已經選擇的矩形等等控制。

      好在邏輯很簡單,我們依照原理圖一步步寫代碼即可:

      image

      4,鼠標移動事件

      在MouseMove事件中,我們通過原理圖可以看到,我們首先要判斷下是否處于連線狀態,防止在選擇矩形時矩形發生移動等變化。

      image

      5,生成連線

      因為我們要在任意兩個矩形間生成連線,所以就不能像上一小節中那樣簡單的定義兩個坐標變量。

      連線會有很多,所以我們先定義一個連線類:

      image

      然后定義一個連線列表的全局變量:

      image

      在生成連線,我們需要知道兩個矩形ID對應的矩形的中心點,所以我實現根據矩形ID求矩形中心點的方法:

      image

      之后就像繪制矩形的方法一樣,我們寫一個維護連線的方法:

      image

      最后,我們在繪制所有矩形和連線的方法中,加上依次繪制所有連線的方法:

      image

      好了,到此我們依照原理圖對代碼改造完畢,也就可以實現視頻的效果2了。

      下面有完整的代碼,大家嘗試一下吧。

      點擊查看代碼
      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows.Forms;
      
      namespace FlowChartDemo
      {
          public partial class FormDemo02V2 : FormBase
          {
              public FormDemo02V2()
              {
                  InitializeComponent();
                  DemoTitle = "第03節隨課Demo  Part2";
                  DemoNote = "效果:在【任意】兩個矩形之間添加【一條】直線,連接兩個形狀的中心";
              }
      
              /// <summary>
              /// 矩形定義
              /// </summary>
              public class RectShape
              {
                  /// <summary>
                  /// 矩形ID
                  /// </summary>
                  public string Id { get; set; }
                  /// <summary>
                  /// 矩形位置和尺寸
                  /// </summary>
                  public Rectangle Rect { get; set; }
              }
      
              /// <summary>
              /// 直線連線定義
              /// </summary>
              public class LineLink
              {
                  /// <summary>
                  /// 連線ID
                  /// </summary>
                  public string Id { get; set; }
                  /// <summary>
                  /// 連線開始形狀ID
                  /// </summary>
                  public string StartShapeId { get; set; }
                  /// <summary>
                  /// 連線結束形狀ID
                  /// </summary>
                  public string EndShapeId { get; set; }
              }
      
              /// <summary>
              /// 當前界面矩形集合
              /// </summary>
              List<RectShape> Shapes = new List<RectShape>();
              /// <summary>
              /// 當前界面連線集合
              /// </summary>
              List<LineLink> Links = new List<LineLink>();
      
              /// <summary>
              /// 畫一個矩形(不同顏色)
              /// </summary>
              /// <param name="g"></param>
              /// <param name="shape"></param>
              void DrawShape2(Graphics g, RectShape shape)
              {
                  var index = Shapes.FindIndex(a => a.Id == shape.Id);
                  g.FillRectangle(GetBrush(index), shape.Rect);
                  g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
              }
      
              /// <summary>
              /// 繪制一條連線
              /// </summary>
              /// <param name="g"></param>
              /// <param name="line"></param>
              void DrawLine(Graphics g,LineLink line)
              {
                  //通過連線的開始形狀ID和結束形狀ID,計算兩個形狀的中心點坐標
                  var startPoint = GetCentertPoint(line.StartShapeId);
                  var endPoint = GetCentertPoint(line.EndShapeId);
                  //繪制一條直線
                  g.DrawLine(Pens.Black, startPoint, endPoint);
              }
      
              /// <summary>
              /// 重新繪制當前所有矩形和連線
              /// </summary>
              /// <param name="g"></param>
              void DrawAll(Graphics g)
              {
                  g.Clear(panel1.BackColor) ;
                  //繪制所有形狀
                  foreach (var sp in Shapes)
                  {
                      DrawShape2(g, sp);
                  }
                  //繪制所有連線
                  foreach (var ln in Links)
                  {
                      DrawLine(g, ln);
                  }
              }
      
              /// <summary>
              /// 當前是否有鼠標按下,且有矩形被選中
              /// </summary>
              bool _isMouseDown = false;
              /// <summary>
              /// 最后一次鼠標的位置
              /// </summary>
              Point _lastMouseLocation = Point.Empty;
              /// <summary>
              /// 當前被鼠標選中的矩形
              /// </summary>
              RectShape _selectedShape = null;
      
              /// <summary>
              /// 添加連線時選中的第一個形狀
              /// </summary>
              RectShape _selectedStartShape = null;
              /// <summary>
              /// 添加連線時選中的第二個形狀
              /// </summary>
              RectShape _selectedEndShape = null;
              /// <summary>
              /// 是否正添加連線
              /// </summary>
              bool _isAddLink = false;
      
              /// <summary>
              /// 獲取不同的背景顏色
              /// </summary>
              /// <param name="i"></param>
              /// <returns></returns>
              Brush GetBrush(int i)
              {
                  switch (i)
                  {
                      case 0: return Brushes.Red;
                      case 1: return Brushes.Green;
                      case 2: return Brushes.Blue;
                      case 3: return Brushes.Orange;
                      case 4: return Brushes.Purple;
                      default: return Brushes.Red;
                  }
              }
      
              /// <summary>
              /// 根據形狀ID獲取形狀的中心點,以作為連線的起點或終點
              /// </summary>
              /// <param name="shapeId"></param>
              /// <returns></returns>
              Point GetCentertPoint(string shapeId)
              {
                  var sp = Shapes.Find(a => a.Id == shapeId);
                  if (sp != null)
                  {
                      var line1X = sp.Rect.X + sp.Rect.Width / 2;
                      var line1Y = sp.Rect.Y + sp.Rect.Height / 2;
                      return new Point(line1X, line1Y);
                  }
                  return Point.Empty;
              }
      
      
              private void toolStripButton1_Click(object sender, EventArgs e)
              {
                  var rs = new RectShape()
                  {
                      Id = "矩形" + (Shapes.Count + 1),
                      Rect = new Rectangle()
                      {
                          X = 50,
                          Y = 50,
                          Width = 100,
                          Height = 100,
                      },
                  };
                  Shapes.Add(rs);
      
                  //重繪所有矩形
                  DrawAll(panel1.CreateGraphics());
              }
      
              private void panel1_MouseDown(object sender, MouseEventArgs e)
              {
                  //當鼠標按下時
      
                  //取最上方的矩形,也就是最后添加的矩形
                  var sp = Shapes.FindLast(a => a.Rect.Contains(e.Location));
                  if (sp != null)
                  {
                      //證明取到了矩形
      
                      //判斷是否正在添加連線
                      if (_isAddLink)
                      {
                          //正在添加連線
                          if (_selectedStartShape == null)
                          {
                              //如果開始形狀還沒選擇,則設置開始形狀
                              _selectedStartShape = sp;
                              toolStripStatusLabel1.Text = "請點擊第2個形狀";
                          }
                          else if (_selectedEndShape == null)
                          {
                              //判斷第2個形狀是否是第1個形狀
                              if (_selectedStartShape.Id == sp.Id)
                              {
                                  toolStripStatusLabel1.Text = "不可選擇同一個形狀,請重新點擊第2個形狀";
                              }
                              else
                              {
                                  //如果結束形狀還沒選擇,則設置結束形狀
                                  _selectedEndShape = sp;
      
                                  //兩個形狀都設置了,便添加一條新連線
                                  Links.Add(new LineLink()
                                  {
                                      Id = "連線" + (Links.Count + 1),
                                      StartShapeId = _selectedStartShape.Id,
                                      EndShapeId = _selectedEndShape.Id,
                                  });
                                  //兩個形狀都已選擇,結束添加連線狀態
                                  _isAddLink = false;
                                  toolStripStatusLabel1.Text = "";
                                  //重繪以顯示連線
                                  DrawAll(panel1.CreateGraphics());
                              }
                          }
      
                      }
                      else
                      {
                          //如果沒有在添加連線,則正常選中矩形
      
                          //設置狀態及選中矩形
                          _isMouseDown = true;
                          _lastMouseLocation = e.Location;
                          _selectedShape = sp;
                      }
                  }
              }
      
              private void panel1_MouseMove(object sender, MouseEventArgs e)
              {
                  //當鼠標移動時
      
                  //如果處于添加連線時,則不移動形狀
                  if (_isAddLink) return;
      
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //改變選中矩形的位置信息,隨著鼠標移動而移動
      
                      //計算鼠標位置變化信息
                      var moveX = e.Location.X - _lastMouseLocation.X;
                      var moveY = e.Location.Y - _lastMouseLocation.Y;
      
                      //將選中形狀的位置進行同樣的變化
                      var oldXY = _selectedShape.Rect.Location;
                      oldXY.Offset(moveX, moveY);
                      _selectedShape.Rect = new Rectangle(oldXY, _selectedShape.Rect.Size);
      
                      //記錄當前鼠標位置
                      _lastMouseLocation.Offset(moveX, moveY);
      
                      //重繪所有矩形
                      DrawAll(panel1.CreateGraphics());
                  }
      
              }
      
              private void panel1_MouseUp(object sender, MouseEventArgs e)
              {
                  //當鼠標松開時
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //重置相關記錄信息
                      _isMouseDown = false;
                      _lastMouseLocation = Point.Empty;
                      _selectedShape = null;
                  }
              }
      
              private void toolStripButton2_Click(object sender, EventArgs e)
              {
                  _isAddLink = true;
                  _selectedStartShape = null;
                  _selectedEndShape = null;
                  toolStripStatusLabel1.Text = "請點擊第1個形狀";
              }
          }
      
      
      }
      
      

      五、實現效果3:添加不同顏色直線,連線去重,中止添加連線

      我們下面實現效果3,這次的效果改動很少,更多的是一些易用性上的優化,我們下面一點點講解。

      (一)原理

      同樣的,我們先來看原理圖,這個原理圖是在上面小節原理圖上增加了新的節點,并使用綠色進行了著重標注。

      image

      可以看到,增加的節點流程就一個,判斷是否已經添加過相同的連線。

      (二)代碼實操

      1,設計器界面

      本次的界面主要增加了中止連線的按鈕。

      image

      2,不同顏色的直線

      我們先來看最簡單的添加不同顏色的直線,這個和上一章不同顏色的矩形實現邏輯是一樣的,獲取不同顏色的畫筆就行了:

      image

      同樣的,繪制直線方法名我們也增加個2,來作下區分,這里只是用來區分,在實現項目及后續教程中就是直接改原方法了,也是貫徹抽象的思路。

      image

      3,連線去重

      我們的連線是連接兩個矩形的中心點,如果多個連線的開始矩形和結束矩形都一樣,是看不出效果的,是沒必要的,所以我們這里添加下去重。

      注:因為本篇教程連線是連接的兩個矩形的中心點,所以有去重的必要。在后續章節,我們連接的就不是矩形的中心了,而是矩形(包括其它形狀)的“連接點”了,連接點的概念很好理解,就是日常使用流程圖時,連線都是到上下左右邊的中間點(當然不止這些),我們后續也會這樣實現。

      我們參照原理圖,在MouseDown事件中,添加去重判斷的代碼:

      image

      3,中止添加連線操作

      我們在添加連線時,可能點錯了開始矩形,在上面小節中,我們是沒辦法結束的,只能繼續選另一個矩形,所以我們增加上中止添加連線操作。

      注:在后續的章節中,我們會講解如何實現更符合操作邏輯的添加及中止連線方式:點按開始形狀的連接點,移動到另一個形狀的連接點上,完成連線操作操作。在移動時有虛線箭頭提示,且松開鼠標自動取消連線。敬請期待。

      實現代碼很簡單,我們只需要設置連線狀態標志為false即可:

      image

      好了,到此我們依照原理圖對代碼改造完畢,也就可以實現視頻的效果3了。

      下面有完整的代碼,大家嘗試一下吧。

      點擊查看代碼
      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Threading.Tasks;
      using System.Windows.Forms;
      
      namespace FlowChartDemo
      {
          public partial class FormDemo02V3 : FormBase
          {
              public FormDemo02V3()
              {
                  InitializeComponent();
                  DemoTitle = "第04節隨課Demo  Part1";
                  DemoNote = "效果:在【任意】兩個矩形之間添加【不同顏色】直線,連線去重,中止添加連線功能";
              }
      
              //記得刪除:中止功能是因為如果因去重而無法添加下一個形狀,而無法移動形狀
      
              /// <summary>
              /// 矩形定義
              /// </summary>
              public class RectShape
              {
                  /// <summary>
                  /// 矩形ID
                  /// </summary>
                  public string Id { get; set; }
                  /// <summary>
                  /// 矩形位置和尺寸
                  /// </summary>
                  public Rectangle Rect { get; set; }
              }
      
              /// <summary>
              /// 直線連線定義
              /// </summary>
              public class LineLink
              {
                  /// <summary>
                  /// 連線ID
                  /// </summary>
                  public string Id { get; set; }
                  /// <summary>
                  /// 連線開始形狀ID
                  /// </summary>
                  public string StartShapeId { get; set; }
                  /// <summary>
                  /// 連線結束形狀ID
                  /// </summary>
                  public string EndShapeId { get; set; }
              }
      
              /// <summary>
              /// 當前界面矩形集合
              /// </summary>
              List<RectShape> Shapes = new List<RectShape>();
              /// <summary>
              /// 當前界面連線集合
              /// </summary>
              List<LineLink> Links = new List<LineLink>();
      
              /// <summary>
              /// 畫一個矩形(不同顏色)
              /// </summary>
              /// <param name="g"></param>
              /// <param name="shape"></param>
              void DrawShape2(Graphics g, RectShape shape)
              {
                  var index = Shapes.FindIndex(a => a.Id == shape.Id);
                  g.FillRectangle(GetBrush(index), shape.Rect);
                  g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
              }
      
              /// <summary>
              /// 繪制一條連線
              /// </summary>
              /// <param name="g"></param>
              /// <param name="line"></param>
              void DrawLine(Graphics g, LineLink line)
              {
                  //通過連線的開始形狀ID和結束形狀ID,計算兩個形狀的中心點坐標
                  var startPoint = GetCentertPoint(line.StartShapeId);
                  var endPoint = GetCentertPoint(line.EndShapeId);
                  //繪制一條直線
                  g.DrawLine(Pens.Black, startPoint, endPoint);
              }
      
              /// <summary>
              /// 繪制一條連線(不同顏色)
              /// </summary>
              /// <param name="g"></param>
              /// <param name="line"></param>
              void DrawLine2(Graphics g, LineLink line)
              {
                  //通過連線的開始形狀ID和結束形狀ID,計算兩個形狀的中心點坐標
                  var startPoint = GetCentertPoint(line.StartShapeId);
                  var endPoint = GetCentertPoint(line.EndShapeId);
      
                  var index = Links.FindIndex(a => a.Id == line.Id);
                  //繪制一條直線
                  g.DrawLine(GetPen(index), startPoint, endPoint);
              }
      
              /// <summary>
              /// 重新繪制當前所有矩形和連線
              /// </summary>
              /// <param name="g"></param>
              void DrawAll(Graphics g)
              {
                  g.Clear(panel1.BackColor) ;
                  //繪制所有形狀
                  foreach (var sp in Shapes)
                  {
                      DrawShape2(g, sp);
                  }
                  //繪制所有連線
                  foreach (var ln in Links)
                  {
                      DrawLine2(g, ln);
                  }
              }
      
              /// <summary>
              /// 當前是否有鼠標按下,且有矩形被選中
              /// </summary>
              bool _isMouseDown = false;
              /// <summary>
              /// 最后一次鼠標的位置
              /// </summary>
              Point _lastMouseLocation = Point.Empty;
              /// <summary>
              /// 當前被鼠標選中的矩形
              /// </summary>
              RectShape _selectedShape = null;
      
              /// <summary>
              /// 添加連線時選中的第一個形狀
              /// </summary>
              RectShape _selectedStartShape = null;
              /// <summary>
              /// 添加連線時選中的第二個形狀
              /// </summary>
              RectShape _selectedEndShape = null;
              /// <summary>
              /// 是否正添加連線
              /// </summary>
              bool _isAddLink = false;
      
              /// <summary>
              /// 獲取不同的背景顏色
              /// </summary>
              /// <param name="i"></param>
              /// <returns></returns>
              Brush GetBrush(int i)
              {
                  switch (i)
                  {
                      case 0: return Brushes.Red;
                      case 1: return Brushes.Green;
                      case 2: return Brushes.Blue;
                      case 3: return Brushes.Orange;
                      case 4: return Brushes.Purple;
                      default: return Brushes.Red;
                  }
              }
              /// <summary>
              /// 獲取不同的畫筆顏色
              /// </summary>
              /// <param name="i"></param>
              /// <returns></returns>
              Pen GetPen(int i)
              {
                  return new Pen(GetBrush(i), 2);
              }
      
              /// <summary>
              /// 根據形狀ID獲取形狀的中心點,以作為連線的起點或終點
              /// </summary>
              /// <param name="shapeId"></param>
              /// <returns></returns>
              Point GetCentertPoint(string shapeId)
              {
                  var sp = Shapes.Find(a => a.Id == shapeId);
                  if (sp != null)
                  {
                      var line1X = sp.Rect.X + sp.Rect.Width / 2;
                      var line1Y = sp.Rect.Y + sp.Rect.Height / 2;
                      return new Point(line1X, line1Y);
                  }
                  return Point.Empty;
              }
      
      
              private void toolStripButton1_Click(object sender, EventArgs e)
              {
                  var rs = new RectShape()
                  {
                      Id = "矩形" + (Shapes.Count + 1),
                      Rect = new Rectangle()
                      {
                          X = 50,
                          Y = 50,
                          Width = 100,
                          Height = 100,
                      },
                  };
                  Shapes.Add(rs);
      
                  //重繪所有矩形
                  DrawAll(panel1.CreateGraphics());
              }
      
              private void panel1_MouseDown(object sender, MouseEventArgs e)
              {
                  //當鼠標按下時
      
                  //取最上方的矩形,也就是最后添加的矩形
                  var sp = Shapes.FindLast(a => a.Rect.Contains(e.Location));
                  if (sp != null)
                  {
                      //證明取到了矩形
      
                      //判斷是否正在添加連線
                      if (_isAddLink)
                      {
                          //正在添加連線
                          if (_selectedStartShape == null)
                          {
                              //如果開始形狀還沒選擇,則設置開始形狀
                              _selectedStartShape = sp;
                              toolStripStatusLabel1.Text = "請點擊第2個形狀";
                          }
                          else if (_selectedEndShape == null)
                          {
                              //判斷第2個形狀是否是第1個形狀
                              if (_selectedStartShape.Id == sp.Id)
                              {
                                  toolStripStatusLabel1.Text = "不可選擇同一個形狀,請重新點擊第2個形狀";
                              }
                              else
                              {
                                  //去重判斷,防止添加重復的連線
                                  if (Links.Any(a => (a.StartShapeId == _selectedStartShape.Id && a.EndShapeId == sp.Id)
                                  //判斷是否存在連線的開始是選中的第1個形狀,結束是選中的第2個形狀。
                                   || (a.EndShapeId == _selectedStartShape.Id && a.StartShapeId == sp.Id)))
                                   //判斷是否存在連線的開始是選中的第2個形狀,結束是選中的第1個形狀。(相當于反向,但畫出來是一條線)
                                  {
                                      toolStripStatusLabel1.Text = "已有連線,請重新點擊第2個形狀";
                                  }
                                  else
                                  {
                                      //如果結束形狀還沒選擇,則設置結束形狀
                                      _selectedEndShape = sp;
      
                                      //兩個形狀都設置了,便添加一條新連線
                                      Links.Add(new LineLink()
                                      {
                                          Id = "連線" + (Links.Count + 1),
                                          StartShapeId = _selectedStartShape.Id,
                                          EndShapeId = _selectedEndShape.Id,
                                      });
                                      //兩個形狀都已選擇,結束添加連線狀態
                                      _isAddLink = false;
                                      toolStripStatusLabel1.Text = "";
                                      //重繪以顯示連線
                                      DrawAll(panel1.CreateGraphics());
                                  }
                              }
                          }
      
                      }
                      else
                      {
                          //如果沒有在添加連線,則正常選中矩形
      
                          //設置狀態及選中矩形
                          _isMouseDown = true;
                          _lastMouseLocation = e.Location;
                          _selectedShape = sp;
                      }
                  }
              }
      
              private void panel1_MouseMove(object sender, MouseEventArgs e)
              {
                  //當鼠標移動時
      
                  //如果處于添加連線時,則不移動形狀
                  if (_isAddLink) return;
      
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //改變選中矩形的位置信息,隨著鼠標移動而移動
      
                      //計算鼠標位置變化信息
                      var moveX = e.Location.X - _lastMouseLocation.X;
                      var moveY = e.Location.Y - _lastMouseLocation.Y;
      
                      //將選中形狀的位置進行同樣的變化
                      var oldXY = _selectedShape.Rect.Location;
                      oldXY.Offset(moveX, moveY);
                      _selectedShape.Rect = new Rectangle(oldXY, _selectedShape.Rect.Size);
      
                      //記錄當前鼠標位置
                      _lastMouseLocation.Offset(moveX, moveY);
      
                      //重繪所有矩形
                      DrawAll(panel1.CreateGraphics());
                  }
      
              }
      
              private void panel1_MouseUp(object sender, MouseEventArgs e)
              {
                  //當鼠標松開時
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //重置相關記錄信息
                      _isMouseDown = false;
                      _lastMouseLocation = Point.Empty;
                      _selectedShape = null;
                  }
              }
      
              private void toolStripButton2_Click(object sender, EventArgs e)
              {
                  _isAddLink = true;
                  _selectedStartShape = null;
                  _selectedEndShape = null;
                  toolStripStatusLabel1.Text = "請點擊第1個形狀";
              }
      
              private void toolStripButton3_Click(object sender, EventArgs e)
              {
                  _isAddLink = false;
                  _selectedStartShape = null;
                  _selectedEndShape = null;
                  toolStripStatusLabel1.Text = "";
                  DrawAll(panel1.CreateGraphics());
              }
          }
      
      
      }
      
      

      六、結語

      本篇教程我們從零實現并完善了在任意兩個矩形中添加矩形的功能,本章都是圍繞這個核心功能進行講解,擴展內容很少,學習起來也很容易。

      下章我們會講一下如何添加其它形狀,如圓形,以及如何在矩形和圓形之間添加連線。后面還會講一下如何優化顯示效果,及拖動時閃爍的問題。敬請期待。

      感謝大家的觀看,本人水平有限,文章不足之處歡迎大家評論指正。

      -[END]-

      posted @ 2025-06-18 11:10  leslie_xin  閱讀(1099)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 男女扒开双腿猛进入爽爽免费看 | 久久这里只有精品免费首页| 营口市| 天啦噜国产精品亚洲精品| 成人性无码专区免费视频| 国产精品美女自慰喷水| av小次郎网站| 一本色道久久综合亚洲精品| 中阳县| 国产一区二区不卡视频在线| 99精品国产综合久久久久五月天| a片免费视频在线观看| 国产又色又爽又黄的视频在线| 国产精品午夜福利91| 久久人妻无码一区二区三区av| 四虎库影成人在线播放| 视频一区视频二区视频三| 在线天堂最新版资源| 国产稚嫩高中生呻吟激情在线视频| 国产嫩草精品网亚洲av| 国产成人高清精品免费软件| 久热这里只有精品12| 最新中文字幕av无码专区不| 成人无码午夜在线观看| 精品超清无码视频在线观看| 亚洲成av人片无码迅雷下载| 亚洲欧美综合中文| 国产成人精品日本亚洲直播| 九九热在线精品免费视频 | 精品中文人妻在线不卡| 亚洲嫩模一区二区三区| A级毛片100部免费看| 克什克腾旗| 国产日韩综合av在线| 又黄又硬又湿又刺激视频免费| 亚洲中文字幕日韩精品| 性视频一区| 最新国产麻豆AⅤ精品无码| 中国老太婆video| 少妇高潮喷水正在播放| 久久久久国产精品熟女影院 |