这不显得您枪法准嘛 發表於 2025-6-10 11:10:00

[原创]《C#高级GDI+实战:从零开发一个流程图》第02章:画一个矩形,能拖动!

<h1 id="一前言">一、前言</h1>
<p>就像开发的教程都从“Hello World!”开篇一样,系列开始,我们也从一个最最简单的功能开始:画一个能拖动的矩形。</p>
<p>顺便说一下,另一篇教程:(原创) GDI+ 之鼠标交互:原理、示例、一步步深入、性能优化 讲的更详细和深入,可以作为补充。</p>
<p>就让我们从一个能拖动的矩形开始我们的流程图开发之旅吧!</p>
<p><strong>相信看完的你,一定会有所收获!</strong></p>
<p>本文地址:https://www.cnblogs.com/lesliexin/p/18919737</p>
<h1 id="二先看效果">二、先看效果</h1>
<p>我们先看下本节所实现的效果:</p>
<iframe src="//player.bilibili.com/player.html?isOutside=true&amp;aid=114647759853008&amp;bvid=BV1wkTRzZEex&amp;cid=30389895238&amp;p=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
<p>可以看到,我们本节课程依次实现了三种效果:</p>
<blockquote>
<p><strong>添加一个可拖动的矩形</strong><br>
<strong>添加多个可拖动的矩形</strong><br>
<strong>添加多个不同颜色的可拖动的矩形</strong>。</p>
</blockquote>
<p>下面我们就来依次看一下这三种效果是怎么一步步实现的。</p>
<p>(注:系列完成时,将会将此演示DEMO程序及完整的源代码工程一起放到Github和Gitee上,为了更好的跟随教程进度,暂时请先参照每篇文章中的代码。)</p>
<h1 id="三实现效果1一个可拖动的矩形">三、实现效果1:一个可拖动的矩形</h1>
<h2 id="一原理">(一)原理</h2>
<p>前言中说的那篇教程已经讲的很详细了,此处简略说下原理:</p>
<blockquote>
<p>画一个矩形 -&gt; 检测鼠标点击、移动等事件 -&gt; 当鼠标点在矩形里时,移动鼠标的同时,计算矩形坐标并重新绘制矩形</p>
</blockquote>
<p>详细的原理流程图如下:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609093823201-555269563.png" alt="image" loading="lazy"></p>
<h2 id="二代码实操">(二)代码实操</h2>
<p>下面我们就依据上面的原理流程图,来一步步编写代码实现。</p>
<h3 id="1设计器界面">1,设计器界面</h3>
<p>设计器界面如下图所示,一个按钮、一个Panel,然后Panel实现了MouseDown、MouseMove、MouseUp事件。</p>
<p>(注:请忽略上面的绿色标签等控件,这是为了做统一化的演示Demo工具,与本篇文章不相关。)</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609094228474-1549314068.png" alt="image" loading="lazy"></p>
<h3 id="2添加矩形的代码">2,添加矩形的代码</h3>
<p>定义一个全局变量,因为好多地方都要用到或修改其值:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609094650149-1586039089.png" alt="image" loading="lazy"></p>
<p>绘制代码很简单,就是GDI+的绘制矩形方法:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609094548211-1720498126.png" alt="image" loading="lazy"></p>
<p>然后我们为“添加矩形”按钮点击事件添加添加矩形的代码:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609094906140-1221218338.png" alt="image" loading="lazy"></p>
<h3 id="3鼠标点击事件实现">3,鼠标点击事件实现</h3>
<p>看上节的流程图,我们可以发现,首要的一步就是要判断鼠标有没有点到矩形上。</p>
<p>同样,我们定义两个全局变量,分别是鼠标点中矩形的标志、和鼠标的当前位置。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609095107346-1542083824.png" alt="image" loading="lazy"></p>
<p>然后我们在MouseDown事件中,判断并对全局变量赋值。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609095224761-1508241001.png" alt="image" loading="lazy"></p>
<h3 id="4鼠标松开事件实现">4,鼠标松开事件实现</h3>
<p>我们先看这个MouseUp事件,这个事件是重置标志和坐标的。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609095444669-637084478.png" alt="image" loading="lazy"></p>
<h3 id="5鼠标移动事件">5,鼠标移动事件</h3>
<p>这个MouseMove事件,就是本节的核心,我们参照流程图,一步步用代码实现即可。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609095548857-936779133.png" alt="image" loading="lazy"></p>
<p>到此,整个效果1已经完全实现了,大家可以尝试尝试。也附上完整的后台代码:</p>
<details>
<summary>点击查看代码</summary>
<pre><code>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节随课DemoPart1";
            DemoNote = "效果:添加【一个】可拖动的矩形";
      }

      /// &lt;summary&gt;
      /// 画矩形
      /// &lt;/summary&gt;
      /// &lt;param name="g"&gt;&lt;/param&gt;
      void DrawRect(Graphics g)
      {
            g.Clear(panel1.BackColor);
            g.FillRectangle(Brushes.Red,Rect);
      }

      /// &lt;summary&gt;
      /// 当前是否有鼠标按下,且有矩形被选中
      /// &lt;/summary&gt;
      bool _isMouseDown = false;
      /// &lt;summary&gt;
      /// 最后一次鼠标的位置
      /// &lt;/summary&gt;
      Point _lastMouseLocation = Point.Empty;
      /// &lt;summary&gt;
      /// 当前矩形
      /// &lt;/summary&gt;
      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;
            }
      }
    }


}

</code></pre>
</details>
<h1 id="四实现效果2多个可拖动的矩形">四、实现效果2:多个可拖动的矩形</h1>
<h2 id="一原理-1">(一)原理</h2>
<p>基本的实现原理和效果1是一样的,不过是多了一步:<strong>判断点击的是多个矩形中的哪个矩形,然后在移动时仅移动选中的矩形。</strong></p>
<p>话不多说,我们直接上代码实操。</p>
<h2 id="二代码实操-1">(二)代码实操</h2>
<p>下面我们就依据上面的原理流程图,来一步步编写代码实现。</p>
<h3 id="1设计器界面-1">1,设计器界面</h3>
<p>设计器界面还是和效果1一样,不再赘述。</p>
<h3 id="2添加矩形的代码-1">2,添加矩形的代码</h3>
<p>因为涉及到多个矩形,所以我们先定义一个类,以标识矩形信息:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609100834268-1175514698.png" alt="image" loading="lazy"></p>
<p>然后我们定义一个矩形列表的全局变量,用于存储添加的所有矩形信息:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101046616-1954382956.png" alt="image" loading="lazy"></p>
<p>绘制代码也作同步调整,遍历的绘制所有矩形:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101211045-73702226.png" alt="image" loading="lazy"></p>
<blockquote>
<p>注意看上面的代码,我们是在效果1的基础上来实现一个遍历调用的方法,<strong>而不是</strong>直接重新写一个遍历方法,或者直接使用GDI+的绘制矩形数组方法,这样写是<strong>为了后续进一步的抽象</strong>,因为我们的目的不是只绘制矩形,还有其它各种各样的形状。具体的我们后续教程会有讲解。</p>
</blockquote>
<p>然后我们为“添加矩形”按钮点击事件添加添加矩形的代码,与效果1的区别是多了一步添加到矩形列表的操作:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101736132-1963525554.png" alt="image" loading="lazy"></p>
<h3 id="3鼠标点击事件实现-1">3,鼠标点击事件实现</h3>
<p>我们看这个MouseDown事件,这里与效果1的区别是要判断点到的是矩形列表中的哪个矩形。<br>
代码如下,我们不多做赘述。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101915789-1162201828.png" alt="image" loading="lazy"></p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101934610-1403430042.png" alt="image" loading="lazy"></p>
<blockquote>
<p>注意看,我们这里判断点到的是哪个矩形时,如果同一个坐标点下有多个矩形,我们是选择最后所添加的矩形。这个很好理解,就是PS中的图层一样,后添加的图层在上面。同样的,在上面绘制所有矩形时也是同样的逻辑,从旧到新,依次绘制,后添加的在上面。</p>
</blockquote>
<h3 id="4鼠标松开事件实现-1">4,鼠标松开事件实现</h3>
<p>我们先看这个MouseUp事件,也效果1的差别是还要重置选中的矩形。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609102541388-744371402.png" alt="image" loading="lazy"></p>
<h3 id="5鼠标移动事件-1">5,鼠标移动事件</h3>
<p>这个MouseMove事件,同样,与效果1的差别就是要用选中的矩形</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609102625302-1486625344.png" alt="image" loading="lazy"></p>
<p>到此,整个效果2已经完全实现了,大家可以尝试尝试。也附上完整的后台代码:</p>
<details>
<summary>点击查看代码</summary>
<pre><code>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节随课DemoPart2";
            DemoNote = "效果:添加【多个】可拖动的矩形";
      }

      /// &lt;summary&gt;
      /// 矩形定义
      /// &lt;/summary&gt;
      public class RectShape
      {
            /// &lt;summary&gt;
            /// 矩形ID
            /// &lt;/summary&gt;
            public string Id { get; set; }
            /// &lt;summary&gt;
            /// 矩形位置和尺寸
            /// &lt;/summary&gt;
            public Rectangle Rect { get; set; }
      }

      /// &lt;summary&gt;
      /// 当前界面矩形集合
      /// &lt;/summary&gt;
      List&lt;RectShape&gt; Shapes = new List&lt;RectShape&gt;();

      /// &lt;summary&gt;
      /// 画一个矩形
      /// &lt;/summary&gt;
      /// &lt;param name="g"&gt;&lt;/param&gt;
      /// &lt;param name="shape"&gt;&lt;/param&gt;
      void DrawShape(Graphics g,RectShape shape)
      {
            g.FillRectangle(Brushes.Red, shape.Rect);
            g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
      }

      /// &lt;summary&gt;
      /// 重新绘制当前所有矩形
      /// &lt;/summary&gt;
      /// &lt;param name="g"&gt;&lt;/param&gt;
      void DrawAllShape(Graphics g)
      {
            g.Clear(panel1.BackColor) ;
            foreach (var sp in Shapes)
            {
                DrawShape(g, sp);
            }
      }

      /// &lt;summary&gt;
      /// 当前是否有鼠标按下,且有矩形被选中
      /// &lt;/summary&gt;
      bool _isMouseDown = false;
      /// &lt;summary&gt;
      /// 最后一次鼠标的位置
      /// &lt;/summary&gt;
      Point _lastMouseLocation = Point.Empty;
      /// &lt;summary&gt;
      /// 当前被鼠标选中的矩形
      /// &lt;/summary&gt;
      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 =&gt; 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;
            }
      }
    }


}

</code></pre>
</details>
<h1 id="五实现效果3多个不同颜色的可拖动的矩形">五、实现效果3:多个不同颜色的可拖动的矩形</h1>
<h2 id="一原理-2">(一)原理</h2>
<p>同样,基本的实现原理和效果2是一样的,不过是多了一步:<strong>添加矩形时,给予不同的颜色。</strong></p>
<p>话不多说,我们直接上代码实操。</p>
<h2 id="二代码实操-2">(二)代码实操</h2>
<p>下面我们就依据上面的原理流程图,来一步步编写代码实现。</p>
<h3 id="1设计器界面-2">1,设计器界面</h3>
<p>设计器界面还是和效果1一样,不再赘述。</p>
<h3 id="2添加矩形的代码-2">2,添加矩形的代码</h3>
<p>定义一个全局变量,不再赘述:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609100834268-1175514698.png" alt="image" loading="lazy"></p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101046616-1954382956.png" alt="image" loading="lazy"></p>
<p>然后我们添加一个根据序号也不同颜色的简单方法:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609103644894-1829463841.png" alt="image" loading="lazy"></p>
<p>同样的,绘制矩形方法我们也稍作调整,增加设置颜色的步骤:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609103727927-711961918.png" alt="image" loading="lazy"></p>
<blockquote>
<p>注意看,我们上面的代码是重写了个新方法并添加个2以作区分,然后绘制所有矩形的地方也同步调整为调用这个新方法。但实际环境中,不需要这样,直接在原方法上修改即可,这样绘制所有矩形的方法也不需要修改。这就是抽象的好处,当然这里体现不明显,但是我们在日常要保持抽象的思想。</p>
</blockquote>
<p>然后“添加矩形”按钮点击事件代码也没有改动:</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609094906140-1221218338.png" alt="image" loading="lazy"></p>
<h3 id="3鼠标点击事件实现-2">3,鼠标点击事件实现</h3>
<p>这个MouseDown事件与效果2一样,不再赘述。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101915789-1162201828.png" alt="image" loading="lazy"></p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609101934610-1403430042.png" alt="image" loading="lazy"></p>
<h3 id="4鼠标松开事件实现-2">4,鼠标松开事件实现</h3>
<p>这个MouseUp事件与效果2一样,不再赘述。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609102541388-744371402.png" alt="image" loading="lazy"></p>
<h3 id="5鼠标移动事件-2">5,鼠标移动事件</h3>
<p>这个MouseMove事件与效果2一样,不再赘述。</p>
<p><img src="https://img2024.cnblogs.com/blog/1686429/202506/1686429-20250609102625302-1486625344.png" alt="image" loading="lazy"></p>
<p>到此,整个效果3已经完全实现了,大家可以尝试尝试。也附上完整的后台代码:</p>
<details>
<summary>点击查看代码</summary>
<pre><code>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节随课DemoPart3";
            DemoNote = "效果:添加【多个】可拖动的矩形,且矩形颜色不一样";
      }

      /// &lt;summary&gt;
      /// 矩形定义
      /// &lt;/summary&gt;
      public class RectShape
      {
            /// &lt;summary&gt;
            /// 矩形ID
            /// &lt;/summary&gt;
            public string Id { get; set; }
            /// &lt;summary&gt;
            /// 矩形位置和尺寸
            /// &lt;/summary&gt;
            public Rectangle Rect { get; set; }
      }

      /// &lt;summary&gt;
      /// 当前界面矩形集合
      /// &lt;/summary&gt;
      List&lt;RectShape&gt; Shapes = new List&lt;RectShape&gt;();

      /// &lt;summary&gt;
      /// 画一个矩形(不同颜色)
      /// &lt;/summary&gt;
      /// &lt;param name="g"&gt;&lt;/param&gt;
      /// &lt;param name="shape"&gt;&lt;/param&gt;
      void DrawShape2(Graphics g, RectShape shape)
      {
            var index = Shapes.FindIndex(a =&gt; a.Id == shape.Id);
            g.FillRectangle(GetBrush(index), shape.Rect);
            g.DrawString(shape.Id, Font, Brushes.White, shape.Rect);
      }

      /// &lt;summary&gt;
      /// 重新绘制当前所有矩形
      /// &lt;/summary&gt;
      /// &lt;param name="g"&gt;&lt;/param&gt;
      void DrawAllShape(Graphics g)
      {
            g.Clear(panel1.BackColor) ;
            foreach (var sp in Shapes)
            {
                DrawShape2(g, sp);
            }
      }

      /// &lt;summary&gt;
      /// 当前是否有鼠标按下,且有矩形被选中
      /// &lt;/summary&gt;
      bool _isMouseDown = false;
      /// &lt;summary&gt;
      /// 最后一次鼠标的位置
      /// &lt;/summary&gt;
      Point _lastMouseLocation = Point.Empty;
      /// &lt;summary&gt;
      /// 当前被鼠标选中的矩形
      /// &lt;/summary&gt;
      RectShape _selectedShape = null;

      /// &lt;summary&gt;
      /// 获取不同的背景颜色
      /// &lt;/summary&gt;
      /// &lt;param name="i"&gt;&lt;/param&gt;
      /// &lt;returns&gt;&lt;/returns&gt;
      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 =&gt; 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;
            }
      }
    }


}

</code></pre>
</details>
<h1 id="六结语">六、结语</h1>
<p>绘制可拖动的矩形,是一切的开始和基础,我们通过本篇教程,了解到了如何一步步由浅入深,如何保持抽象的思想,为后续的开发打好基础。</p>
<p>本篇文章没有什么复杂的代码,都很常见,一个复杂的系统、繁复的功能都是由这样一个个简单的组件有机的组合成的。我们下篇教程,将会讲解如何在形状之间添加一条连线,这个也是流程图的基础。</p>
<p>感谢大家的观看,本人水平有限,文章不足之处欢迎大家评论指正。</p>
<p>--</p><br><br>
来源:https://www.cnblogs.com/lesliexin/p/18919737
頁: [1]
查看完整版本: [原创]《C#高级GDI+实战:从零开发一个流程图》第02章:画一个矩形,能拖动!