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

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

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

      [原創]《C#高級GDI+實戰:從零開發一個流程圖》第02章:畫一個矩形,能拖動!

      一、前言

      就像開發的教程都從“Hello World!”開篇一樣,系列開始,我們也從一個最最簡單的功能開始:畫一個能拖動的矩形。

      順便說一下,另一篇教程:(原創)[C#] GDI+ 之鼠標交互:原理、示例、一步步深入、性能優化 講的更詳細和深入,可以作為補充。

      就讓我們從一個能拖動的矩形開始我們的流程圖開發之旅吧!

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

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

      二、先看效果

      我們先看下本節所實現的效果:

      可以看到,我們本節課程依次實現了三種效果:

      添加一個可拖動的矩形
      添加多個可拖動的矩形
      添加多個不同顏色的可拖動的矩形

      下面我們就來依次看一下這三種效果是怎么一步步實現的。

      (注:系列完成時,將會將此演示DEMO程序及完整的源代碼工程一起放到Github和Gitee上,為了更好的跟隨教程進度,暫時請先參照每篇文章中的代碼。)

      三、實現效果1:一個可拖動的矩形

      (一)原理

      前言中說的那篇教程已經講的很詳細了,此處簡略說下原理:

      畫一個矩形 -> 檢測鼠標點擊、移動等事件 -> 當鼠標點在矩形里時,移動鼠標的同時,計算矩形坐標并重新繪制矩形

      詳細的原理流程圖如下:

      image

      (二)代碼實操

      下面我們就依據上面的原理流程圖,來一步步編寫代碼實現。

      1,設計器界面

      設計器界面如下圖所示,一個按鈕、一個Panel,然后Panel實現了MouseDown、MouseMove、MouseUp事件。

      (注:請忽略上面的綠色標簽等控件,這是為了做統一化的演示Demo工具,與本篇文章不相關。)

      image

      2,添加矩形的代碼

      定義一個全局變量,因為好多地方都要用到或修改其值:

      image

      繪制代碼很簡單,就是GDI+的繪制矩形方法:

      image

      然后我們為“添加矩形”按鈕點擊事件添加添加矩形的代碼:

      image

      3,鼠標點擊事件實現

      看上節的流程圖,我們可以發現,首要的一步就是要判斷鼠標有沒有點到矩形上。

      同樣,我們定義兩個全局變量,分別是鼠標點中矩形的標志、和鼠標的當前位置。

      image

      然后我們在MouseDown事件中,判斷并對全局變量賦值。

      image

      4,鼠標松開事件實現

      我們先看這個MouseUp事件,這個事件是重置標志和坐標的。

      image

      5,鼠標移動事件

      這個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 FormDemo01V1 : FormBase
          {
              public FormDemo01V1()
              {
                  InitializeComponent();
                  DemoTitle = "第02節隨課Demo  Part1";
                  DemoNote = "效果:添加【一個】可拖動的矩形";
              }
      
              /// <summary>
              /// 畫矩形
              /// </summary>
              /// <param name="g"></param>
              void DrawRect(Graphics g)
              {
                  g.Clear(panel1.BackColor);
                  g.FillRectangle(Brushes.Red,Rect);
              }
      
              /// <summary>
              /// 當前是否有鼠標按下,且有矩形被選中
              /// </summary>
              bool _isMouseDown = false;
              /// <summary>
              /// 最后一次鼠標的位置
              /// </summary>
              Point _lastMouseLocation = Point.Empty;
              /// <summary>
              /// 當前矩形
              /// </summary>
              Rectangle Rect = Rectangle.Empty;
      
      
              private void toolStripButton1_Click(object sender, EventArgs e)
              {
                  if (!Rect.IsEmpty)
                  {
                      MessageBox.Show("已有矩形,無法再次添加");
                      return;
                  }
                  Rect = new Rectangle()
                  {
                      X = 50,
                      Y = 50,
                      Width = 100,
                      Height = 100,
                  };
                  //重繪所有矩形
                  DrawRect(panel1.CreateGraphics());
              }
      
              private void panel1_MouseDown(object sender, MouseEventArgs e)
              {
                  //當鼠標按下時
      
                  if (Rect.Contains(e.Location))
                  {
                      //證明鼠標點到了矩形
      
                      //設置狀態及選中矩形
                      _isMouseDown = true;
                      _lastMouseLocation = e.Location;
                  }
              }
      
              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 = Rect.Location;
                      oldXY.Offset(moveX, moveY);
                      Rect = new Rectangle(oldXY, Rect.Size);
      
                      //記錄當前鼠標位置
                      _lastMouseLocation.Offset(moveX, moveY);
      
                      //重繪所有矩形
                      DrawRect(panel1.CreateGraphics());
                  }
      
              }
      
              private void panel1_MouseUp(object sender, MouseEventArgs e)
              {
                  //當鼠標松開時
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //重置相關記錄信息
                      _isMouseDown = false;
                      _lastMouseLocation = Point.Empty;
                  }
              }
          }
      
      
      }
      
      

      四、實現效果2:多個可拖動的矩形

      (一)原理

      基本的實現原理和效果1是一樣的,不過是多了一步:判斷點擊的是多個矩形中的哪個矩形,然后在移動時僅移動選中的矩形。

      話不多說,我們直接上代碼實操。

      (二)代碼實操

      下面我們就依據上面的原理流程圖,來一步步編寫代碼實現。

      1,設計器界面

      設計器界面還是和效果1一樣,不再贅述。

      2,添加矩形的代碼

      因為涉及到多個矩形,所以我們先定義一個類,以標識矩形信息:

      image

      然后我們定義一個矩形列表的全局變量,用于存儲添加的所有矩形信息:

      image

      繪制代碼也作同步調整,遍歷的繪制所有矩形:

      image

      注意看上面的代碼,我們是在效果1的基礎上來實現一個遍歷調用的方法,而不是直接重新寫一個遍歷方法,或者直接使用GDI+的繪制矩形數組方法,這樣寫是為了后續進一步的抽象,因為我們的目的不是只繪制矩形,還有其它各種各樣的形狀。具體的我們后續教程會有講解。

      然后我們為“添加矩形”按鈕點擊事件添加添加矩形的代碼,與效果1的區別是多了一步添加到矩形列表的操作:

      image

      3,鼠標點擊事件實現

      我們看這個MouseDown事件,這里與效果1的區別是要判斷點到的是矩形列表中的哪個矩形。
      代碼如下,我們不多做贅述。

      image

      image

      注意看,我們這里判斷點到的是哪個矩形時,如果同一個坐標點下有多個矩形,我們是選擇最后所添加的矩形。這個很好理解,就是PS中的圖層一樣,后添加的圖層在上面。同樣的,在上面繪制所有矩形時也是同樣的邏輯,從舊到新,依次繪制,后添加的在上面。

      4,鼠標松開事件實現

      我們先看這個MouseUp事件,也效果1的差別是還要重置選中的矩形。

      image

      5,鼠標移動事件

      這個MouseMove事件,同樣,與效果1的差別就是要用選中的矩形

      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 FormDemo01V2 : FormBase
          {
              public FormDemo01V2()
              {
                  InitializeComponent();
                  DemoTitle = "第02節隨課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>
              List<RectShape> Shapes = new List<RectShape>();
      
              /// <summary>
              /// 畫一個矩形
              /// </summary>
              /// <param name="g"></param>
              /// <param name="shape"></param>
              void DrawShape(Graphics g,RectShape shape)
              {
                  g.FillRectangle(Brushes.Red, shape.Rect);
                  g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
              }
      
              /// <summary>
              /// 重新繪制當前所有矩形
              /// </summary>
              /// <param name="g"></param>
              void DrawAllShape(Graphics g)
              {
                  g.Clear(panel1.BackColor) ;
                  foreach (var sp in Shapes)
                  {
                      DrawShape(g, sp);
                  }
              }
      
              /// <summary>
              /// 當前是否有鼠標按下,且有矩形被選中
              /// </summary>
              bool _isMouseDown = false;
              /// <summary>
              /// 最后一次鼠標的位置
              /// </summary>
              Point _lastMouseLocation = Point.Empty;
              /// <summary>
              /// 當前被鼠標選中的矩形
              /// </summary>
              RectShape _selectedShape = null;
      
      
              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);
                  //重繪所有矩形
                  DrawAllShape(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);
      
                      //重繪所有矩形
                      DrawAllShape(panel1.CreateGraphics());
                  }
      
              }
      
              private void panel1_MouseUp(object sender, MouseEventArgs e)
              {
                  //當鼠標松開時
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //重置相關記錄信息
                      _isMouseDown = false;
                      _lastMouseLocation = Point.Empty;
                      _selectedShape = null;
                  }
              }
          }
      
      
      }
      
      

      五、實現效果3:多個不同顏色的可拖動的矩形

      (一)原理

      同樣,基本的實現原理和效果2是一樣的,不過是多了一步:添加矩形時,給予不同的顏色。

      話不多說,我們直接上代碼實操。

      (二)代碼實操

      下面我們就依據上面的原理流程圖,來一步步編寫代碼實現。

      1,設計器界面

      設計器界面還是和效果1一樣,不再贅述。

      2,添加矩形的代碼

      定義一個全局變量,不再贅述:

      image

      image

      然后我們添加一個根據序號也不同顏色的簡單方法:

      image

      同樣的,繪制矩形方法我們也稍作調整,增加設置顏色的步驟:

      image

      注意看,我們上面的代碼是重寫了個新方法并添加個2以作區分,然后繪制所有矩形的地方也同步調整為調用這個新方法。但實際環境中,不需要這樣,直接在原方法上修改即可,這樣繪制所有矩形的方法也不需要修改。這就是抽象的好處,當然這里體現不明顯,但是我們在日常要保持抽象的思想。

      然后“添加矩形”按鈕點擊事件代碼也沒有改動:

      image

      3,鼠標點擊事件實現

      這個MouseDown事件與效果2一樣,不再贅述。

      image

      image

      4,鼠標松開事件實現

      這個MouseUp事件與效果2一樣,不再贅述。

      image

      5,鼠標移動事件

      這個MouseMove事件與效果2一樣,不再贅述。

      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 FormDemo01V3 : FormBase
          {
              public FormDemo01V3()
              {
                  InitializeComponent();
                  DemoTitle = "第02節隨課Demo  Part3";
                  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 DrawAllShape(Graphics g)
              {
                  g.Clear(panel1.BackColor) ;
                  foreach (var sp in Shapes)
                  {
                      DrawShape2(g, sp);
                  }
              }
      
              /// <summary>
              /// 當前是否有鼠標按下,且有矩形被選中
              /// </summary>
              bool _isMouseDown = false;
              /// <summary>
              /// 最后一次鼠標的位置
              /// </summary>
              Point _lastMouseLocation = Point.Empty;
              /// <summary>
              /// 當前被鼠標選中的矩形
              /// </summary>
              RectShape _selectedShape = null;
      
              /// <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;
                  }
              }
      
              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);
                  //重繪所有矩形
                  DrawAllShape(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);
      
                      //重繪所有矩形
                      DrawAllShape(panel1.CreateGraphics());
                  }
      
              }
      
              private void panel1_MouseUp(object sender, MouseEventArgs e)
              {
                  //當鼠標松開時
                  if (_isMouseDown)
                  {
                      //當且僅當:有鼠標按下且有矩形被選中時,才進行后續操作
      
                      //重置相關記錄信息
                      _isMouseDown = false;
                      _lastMouseLocation = Point.Empty;
                      _selectedShape = null;
                  }
              }
          }
      
      
      }
      
      

      六、結語

      繪制可拖動的矩形,是一切的開始和基礎,我們通過本篇教程,了解到了如何一步步由淺入深,如何保持抽象的思想,為后續的開發打好基礎。

      本篇文章沒有什么復雜的代碼,都很常見,一個復雜的系統、繁復的功能都是由這樣一個個簡單的組件有機的組合成的。我們下篇教程,將會講解如何在形狀之間添加一條連線,這個也是流程圖的基礎。

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

      -[END]-

      posted @ 2025-06-10 11:10  leslie_xin  閱讀(1692)  評論(15)    收藏  舉報
      主站蜘蛛池模板: 亚洲国产精品综合久久20| 色婷婷五月综合久久| 欧美日本一区二区视频在线观看| 国产三级精品三级在线看| 成人无码午夜在线观看| 亚洲精品区午夜亚洲精品区| 免费视频成人片在线观看| 日韩精品国产中文字幕| 蜜臀av在线观看| 日本免费一区二区三区日本| 大胸美女被吃奶爽死视频| 国产精品一二三入口播放| 老师扒下内裤让我爽了一夜| 国产精品福利自产拍久久| 久热这里只有精品视频六| 亚洲视频免费一区二区三区| 精品国精品国自产在国产| 亚洲精品国产电影| 自拍视频一区二区三区四区| 东方四虎在线观看av| 日韩精品中文字幕有码| аⅴ天堂中文在线网| 国产成人精品无码免费看| 天天干天天日| 国产精品久久久久久无毒不卡| 亚洲av二区三区在线| 亚洲一区成人av在线| 亚洲色一色噜一噜噜噜| 亚洲天堂av免费在线看| 中文字幕日韩一区二区不卡| 丝袜美腿亚洲综合在线观看视频| 美女网站免费观看视频| 精品视频在线观看免费观看| 欧洲精品色在线观看| 国产精品v片在线观看不卡| 欧美国产激情18| 亚洲av一本二本三本| 国产欧美日韩亚洲一区二区三区| 宜宾市| 久热色视频精品在线观看| 石家庄市|