溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C# 實(shí)現(xiàn)拖拉控件改變位置與大小的方法

發(fā)布時(shí)間:2020-09-12 00:19:34 來源:腳本之家 閱讀:404 作者:Hugo20 欄目:編程語言

前言:

很多時(shí)候我們需要在運(yùn)行時(shí),動(dòng)態(tài)地改變控件的位置以及大小,以獲得更好的布局。比如說實(shí)際項(xiàng)目中的可自定義的報(bào)表、可自定義的單據(jù)等諸如此類。它們有個(gè)特點(diǎn)就是允許客戶或者二次開發(fā)人員設(shè)計(jì)它們需要的界面設(shè)置功能。

本人以前也做過可自定義系統(tǒng),包括界面和功能,主要為了減少開發(fā)人員的工作量以及程序的靈活性和健壯性。

本篇主要討論下,在運(yùn)行時(shí)如何實(shí)現(xiàn)拖拉控件,達(dá)到改變控件位置與大小。功能將模擬VS設(shè)計(jì)界面時(shí)的拖拉功能。

(本篇暫不涉及多控件同時(shí)操作)

一、技術(shù)概述

其實(shí)實(shí)現(xiàn)運(yùn)行時(shí)控件的拖拉并不難,主要是改變控件的Location與Size即可。動(dòng)態(tài)調(diào)整時(shí)再捕獲MouseDown、MouseMove及MouseUp事件來實(shí)時(shí)修改上述兩個(gè)屬性就可以實(shí)現(xiàn)。

二、功能規(guī)劃

在此之前,我們先來看下.net設(shè)計(jì)界面,一旦選中某個(gè)控件時(shí),將會(huì)出現(xiàn)如下圖的邊框:

C# 實(shí)現(xiàn)拖拉控件改變位置與大小的方法

之后就可以通過拖拉出現(xiàn)的邊框改變其大小。而改變控件的位置,實(shí)際上是當(dāng)鼠標(biāo)點(diǎn)擊在控件內(nèi)部拖動(dòng)時(shí)實(shí)現(xiàn)的。

所有本例也將功能分為兩個(gè)部分實(shí)現(xiàn),分別為控件內(nèi)部拖動(dòng)改變位置與控件邊框拖拉改變大小。

三、具體實(shí)現(xiàn)

1.拖動(dòng)控件改變位置

首先,新建一個(gè)項(xiàng)目,然后添加一個(gè)類,取名叫MoveControl,該類用來給控件掛載事件實(shí)現(xiàn)拖動(dòng)。

接著在該類中添加字段currentControl,用來保存需要操作的控件,即通過構(gòu)造函數(shù)傳遞的控件。

接著創(chuàng)建一方法--AddEvents,用來給當(dāng)前的控件掛載事件。

代碼如下: 

DragControl

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace DragControl
{
 public class MoveControl
 {
  #region Constructors
  public MoveControl(Control ctrl)
  {
   currentControl = ctrl;
   AddEvents();
  }
  #endregion
  #region Fields
  private Control currentControl; //傳入的控件
  #endregion
  #region Properties
  #endregion
  #region Methods
  /// <summary>
  /// 掛載事件
  /// </summary>
  private void AddEvents()
  {
   currentControl.MouseClick += new MouseEventHandler(MouseClick);
   currentControl.MouseDown += new MouseEventHandler(MouseDown);
   currentControl.MouseMove += new MouseEventHandler(MouseMove);
   currentControl.MouseUp += new MouseEventHandler(MouseUp);
  }
  #endregion
  #region Events
  /// <summary>
  /// 鼠標(biāo)單擊事件:用來顯示邊框
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  void MouseClick(object sender, MouseEventArgs e)
  {
  }
  /// <summary>
  /// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
  /// </summary>
  void MouseDown(object sender, MouseEventArgs e)
  {
  }
  /// <summary>
  /// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
  /// </summary>
  void MouseMove(object sender, MouseEventArgs e)
  {
  }
  /// <summary>
  /// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
  /// </summary>
  void MouseUp(object sender, MouseEventArgs e)
  {
  }
  #endregion
 }
}

接著我們需要實(shí)現(xiàn)MouseDown、MouseMove、MouseUp三個(gè)事件。

不過在此之前,我們必須要弄清楚,移動(dòng)即表示坐標(biāo)的改變,所以必定要有個(gè)起始坐標(biāo)和終點(diǎn)坐標(biāo)。

所以我們在MoveControl類中加入兩個(gè)字段。

private Point pPoint; //上個(gè)鼠標(biāo)坐標(biāo) private Point cPoint; //當(dāng)前鼠標(biāo)坐標(biāo)

而且在開始拖動(dòng)之前,我們肯定需要先單擊一次控件。在MouseDown時(shí)獲取當(dāng)前光標(biāo)的位置,保存到pPoint中。

(此處用Cursor獲得坐標(biāo)的好處,就是忽略掉容器的麻煩問題)

/// <summary>
/// 鼠標(biāo)單擊事件:用來顯示邊框
/// </summary>
 void MouseClick(object sender, MouseEventArgs e)
 {
  pPoint = Cursor.Position; 
 }
 

接著便實(shí)現(xiàn)MouseMove的事件,當(dāng)鼠標(biāo)左鍵按下時(shí),接著移動(dòng)鼠標(biāo)后,繼續(xù)鼠標(biāo)移動(dòng)后的坐標(biāo),然后與MouseDown時(shí)記下的坐標(biāo)相減,就得到鼠標(biāo)的位移值,接著控件的Location加上該位移值即可,然后更新pPoint?! ?/p>

/// <summary>
  /// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
  /// </summary>
  void MouseMove(object sender, MouseEventArgs e)
  {
   Cursor.Current = Cursors.SizeAll; //當(dāng)鼠標(biāo)處于控件內(nèi)部時(shí),顯示光標(biāo)樣式為SizeAll
   //當(dāng)鼠標(biāo)左鍵按下時(shí)才觸發(fā)
   if (e.Button == MouseButtons.Left)
   {
    cPoint = Cursor.Position; //獲得當(dāng)前鼠標(biāo)位置
    int x = cPoint.X - pPoint.X;
    int y = cPoint.Y - pPoint.Y;
    currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
    pPoint = cPoint;
   }
  }

由于此時(shí)還沒涉及到邊框,所以MouseUp暫時(shí)不用處理。至此拖動(dòng)的基本功能已經(jīng)實(shí)現(xiàn)!

目前MoveControl的完整代碼如下:

MoveControl

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace DragControl
{
 public class MoveControl
 {
  #region Constructors
  public MoveControl(Control ctrl)
  {
   currentControl = ctrl;
   AddEvents();
  }
  #endregion
  #region Fields
  private Control currentControl; //傳入的控件
  private Point pPoint; //上個(gè)鼠標(biāo)坐標(biāo)
  private Point cPoint; //當(dāng)前鼠標(biāo)坐標(biāo)
  #endregion
  #region Properties
  #endregion
  #region Methods
  /// <summary>
  /// 掛載事件
  /// </summary>
  private void AddEvents()
  {
   currentControl.MouseDown += new MouseEventHandler(MouseDown);
   currentControl.MouseMove += new MouseEventHandler(MouseMove);
   currentControl.MouseUp += new MouseEventHandler(MouseUp);
  }
  /// <summary>
  /// 繪制拖拉時(shí)的黑色邊框
  /// </summary>
  public static void DrawDragBound(Control ctrl)
  {
   ctrl.Refresh();
   Graphics g = ctrl.CreateGraphics();
   int width = ctrl.Width;
   int height = ctrl.Height;
   Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
    new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
   g.DrawLines(new Pen(Color.Black), ps);
  } 
  #endregion
  #region Events
  /// <summary>
  /// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
  /// </summary>
  void MouseDown(object sender, MouseEventArgs e)
  {
   pPoint = Cursor.Position;
  }
  /// <summary>
  /// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
  /// </summary>
  void MouseMove(object sender, MouseEventArgs e)
  {
   Cursor.Current = Cursors.SizeAll; //當(dāng)鼠標(biāo)處于控件內(nèi)部時(shí),顯示光標(biāo)樣式為SizeAll
   //當(dāng)鼠標(biāo)左鍵按下時(shí)才觸發(fā)
   if (e.Button == MouseButtons.Left)
   {
    MoveControl.DrawDragBound(this.currentControl);
    cPoint = Cursor.Position; //獲得當(dāng)前鼠標(biāo)位置
    int x = cPoint.X - pPoint.X;
    int y = cPoint.Y - pPoint.Y;
    currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
    pPoint = cPoint;
   }
  }
  /// <summary>
  /// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
  /// </summary>
  void MouseUp(object sender, MouseEventArgs e)
  {
   this.currentControl.Refresh();
  }
  #endregion
 }
}

下面我們來測試下拖動(dòng)的功能。

創(chuàng)建一個(gè)Form窗體,可以再界面上添加你要測試的控件類型,此處我只用TextBox左下測試。在Load的中添加以下代碼,將Form中的所有控件掛載上拖拉功能。

private void Form1_Load(object sender, EventArgs e)
{
 foreach (Control ctrl in this.Controls)
 {
  new MoveControl(ctrl);
 }
}

  此時(shí),有心人可能會(huì)發(fā)現(xiàn)VS中拖動(dòng)控件時(shí),將會(huì)出現(xiàn)黑色邊框,而處于沒有。

這也很簡單,我們在MouseMove時(shí)加上如下代碼即可。

/// <summary>
/// 繪制拖拉時(shí)的黑色邊框
/// </summary>
public static void DrawDragBound(Control ctrl)
{
 ctrl.Refresh();
 Graphics g = ctrl.CreateGraphics();
 int width = ctrl.Width;
 int height = ctrl.Height;
 Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
  new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
 g.DrawLines(new Pen(Color.Black), ps);
} 

/// <summary>
/// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
/// </summary>
void MouseMove(object sender, MouseEventArgs e)
{
 Cursor.Current = Cursors.SizeAll; //當(dāng)鼠標(biāo)處于控件內(nèi)部時(shí),顯示光標(biāo)樣式為SizeAll
 //當(dāng)鼠標(biāo)左鍵按下時(shí)才觸發(fā)
 if (e.Button == MouseButtons.Left)
 {
  MoveControl.DrawDragBound(this.currentControl);
  cPoint = Cursor.Position; //獲得當(dāng)前鼠標(biāo)位置
  int x = cPoint.X - pPoint.X;
  int y = cPoint.Y - pPoint.Y;
  currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
  pPoint = cPoint;
 }
}

同時(shí)要在MoveUp的時(shí)候,刷新一下自己,讓黑色邊框消失掉!  

/// <summary>
/// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
/// </summary>
void MouseUp(object sender, MouseEventArgs e)
{
 this.currentControl.Refresh();
}

接著用沒有邊框的控件測試下就會(huì)很明顯。如下圖所示:  

C# 實(shí)現(xiàn)拖拉控件改變位置與大小的方法

2.通過邊框拖拉控件改變大小

此處的主要思路為:點(diǎn)擊控件的時(shí)候,創(chuàng)建一個(gè)自定義的用戶控件,該用戶控件響應(yīng)區(qū)域就是傳入控件的邊框區(qū)域,同時(shí)給它畫上虛線與8個(gè)小圓圈。

第一、創(chuàng)建用戶控件--FrameControl(邊框控件),然后增加一個(gè)字段用來保存?zhèn)魅氲目丶?,還有加載事件,此處類同前面的MoveControl。

FrameControl

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace DragControl
{
public partial class FrameControl : UserControl
{
#region Constructors
public FrameControl(Control ctrl)
{
 baseControl = ctrl;
 AddEvents();
}
#endregion
#region Fields
Control baseControl; //基礎(chǔ)控件,即被包圍的控件
#endregion
#region Methods
/// <summary>
/// 加載事件
/// </summary>
private void AddEvents()
{
 this.Name = "FrameControl" + baseControl.Name;
 this.MouseDown += new MouseEventHandler(FrameControl_MouseDown);
 this.MouseMove += new MouseEventHandler(FrameControl_MouseMove);
 this.MouseUp += new MouseEventHandler(FrameControl_MouseUp);
}
#endregion
#region Events
/// <summary>
/// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
/// </summary>
void FrameControl_MouseDown(object sender, MouseEventArgs e)
{
}
/// <summary>
/// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
/// </summary>
void FrameControl_MouseMove(object sender, MouseEventArgs e)
{
}
/// <summary>
/// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
/// </summary>
void FrameControl_MouseUp(object sender, MouseEventArgs e)
{
}
#endregion
}
}

做完這些準(zhǔn)備工作后,將到了主要的部分,就是給控件畫邊框。

整個(gè)邊框分為三個(gè)部分:四邊框(用來設(shè)置可視區(qū)域與區(qū)域)+四條虛線(只用來顯示)+八個(gè)小圓圈(用來斜角拖拉)。

所以要建立三個(gè)字段,用來分別保存這個(gè)數(shù)據(jù)。

Rectangle[] smallRects = new Rectangle[8];//邊框中的八個(gè)小圓圈
Rectangle[] sideRects = new Rectangle[4];//四條邊框,用來做響應(yīng)區(qū)域
Point[] linePoints = new Point[5];//四條邊,用于畫虛線

接著就是創(chuàng)建用戶控件的可視區(qū)域,和上面的三個(gè)變量數(shù)值。

(以下計(jì)算位置的代碼,有興趣的人可以研究下,沒有的就直接Copy)  

創(chuàng)建邊框

#region 創(chuàng)建邊框
/// <summary>
/// 建立控件可視區(qū)域
/// </summary>
private void CreateBounds()
{
 //創(chuàng)建邊界
 int X = baseControl.Bounds.X - square.Width - 1;
 int Y = baseControl.Bounds.Y - square.Height - 1;
 int Height = baseControl.Bounds.Height + (square.Height * 2) + 2;
 int Width = baseControl.Bounds.Width + (square.Width * 2) + 2;
 this.Bounds = new Rectangle(X, Y, Width, Height);
 this.BringToFront();
 SetRectangles();
 //設(shè)置可視區(qū)域
 this.Region = new Region(BuildFrame());
 g = this.CreateGraphics();
}
/// <summary>
/// 設(shè)置定義8個(gè)小矩形的范圍
/// </summary>
void SetRectangles()
{
 //左上
 smallRects[0] = new Rectangle(new Point(0, 0), square);
 //右上
 smallRects[1] = new Rectangle(new Point(this.Width - square.Width - 1, 0), square);
 //左下
 smallRects[2] = new Rectangle(new Point(0, this.Height - square.Height - 1), square);
 //右下
 smallRects[3] = new Rectangle(new Point(this.Width - square.Width - 1, this.Height - square.Height - 1), square);
 //上中
 smallRects[4] = new Rectangle(new Point(this.Width / 2 - 1, 0), square);
 //下中
 smallRects[5] = new Rectangle(new Point(this.Width / 2 - 1, this.Height - square.Height - 1), square);
 //左中
 smallRects[6] = new Rectangle(new Point(0, this.Height / 2 - 1), square);
 //右中
 smallRects[7] = new Rectangle(new Point(square.Width + baseControl.Width + 1, this.Height / 2 - 1), square);
 //四條邊線
 //左上
 linePoints[0] = new Point(square.Width / 2, square.Height / 2);
 //右上
 linePoints[1] = new Point(this.Width - square.Width / 2 - 1, square.Height / 2);
 //右下
 linePoints[2] = new Point(this.Width - square.Width / 2 - 1, this.Height - square.Height / 2);
 //左下
 linePoints[3] = new Point(square.Width / 2, this.Height - square.Height / 2 - 1);
 //左上
 linePoints[4] = new Point(square.Width / 2, square.Height / 2);
 //整個(gè)包括周圍邊框的范圍
 ControlRect = new Rectangle(new Point(0, 0), this.Bounds.Size);
}
/// <summary>
/// 設(shè)置邊框控件可視區(qū)域
/// </summary>
/// <returns></returns>
private GraphicsPath BuildFrame()
{
 GraphicsPath path = new GraphicsPath();
 //上邊框
 sideRects[0] = new Rectangle(0, 0, this.Width - square.Width - 1, square.Height + 1);
 //左邊框
 sideRects[1] = new Rectangle(0, square.Height + 1, square.Width + 1, this.Height - square.Height - 1);
 //下邊框
 sideRects[2] = new Rectangle(square.Width + 1, this.Height - square.Height - 1, this.Width - square.Width - 1, square.Height + 1);
 //右邊框
 sideRects[3] = new Rectangle(this.Width - square.Width - 1, 0, square.Width + 1, this.Height - square.Height - 1);
 path.AddRectangle(sideRects[0]);
 path.AddRectangle(sideRects[1]);
 path.AddRectangle(sideRects[2]);
 path.AddRectangle(sideRects[3]);
 return path;
}
#endregion

設(shè)置完位置后,接著就是繪制的工作。增加一個(gè)Draw的方法用來畫,同時(shí)設(shè)置為Public。此處不用控件的Paint,而是讓用戶調(diào)用,只因?yàn)檫@樣方便在不同控件之間切換,也就是一個(gè)容器中,只有當(dāng)前控件有邊框。

/// <summary>
/// 繪圖
/// </summary>
public void Draw()
{
 this.BringToFront();
 Pen pen = new Pen(Color.Black);
 pen.DashStyle = DashStyle.Dot;//設(shè)置為虛線,用虛線畫四邊,模擬微軟效果
 g.DrawLines(pen, linePoints);//繪制四條邊線
 g.FillRectangles(Brushes.White, smallRects); //填充8個(gè)小矩形的內(nèi)部
 foreach (Rectangle smallRect in smallRects)
 {
  g.DrawEllipse(Pens.Black, smallRect); //繪制8個(gè)小橢圓
 }
 //g.DrawRectangles(Pens.Black, smallRects); //繪制8個(gè)小矩形的黑色邊線
}

做到這里,我們可以去前臺(tái)看一下效果,不過再此之前,我們需要調(diào)用該用戶控件。

調(diào)用的地方就是在控件上點(diǎn)擊的時(shí)候,所以在MoveControl中加入MouseClick的事件。

/// <summary>
/// 鼠標(biāo)單擊事件:用來顯示邊框
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void MouseClick(object sender, MouseEventArgs e)
{
 this.currentControl.Parent.Refresh();//刷新父容器,清除掉其他控件的邊框
 this.currentControl.BringToFront();
 fc = new FrameControl(this.currentControl);
 this.currentControl.Parent.Controls.Add(fc);
 fc.Visible = true;
 fc.Draw();
}

這時(shí)有了邊框之后會(huì)有一個(gè)小問題,就是拖動(dòng)控件的時(shí)候,控件移動(dòng)了,但是邊框還留在原地。

所以,這里需要注意的,就是移動(dòng)的時(shí)候,將邊框控件隱藏掉,當(dāng)MouseUp的時(shí)候再顯示。

此時(shí)的完整代碼如下:

MoveControl

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace DragControl
{
public class MoveControl
{
 #region Constructors
 public MoveControl(Control ctrl)
 {
  currentControl = ctrl;
  AddEvents();
 }
 #endregion
 #region Fields
 private Control currentControl; //傳入的控件
 private Point pPoint; //上個(gè)鼠標(biāo)坐標(biāo)
 private Point cPoint; //當(dāng)前鼠標(biāo)坐標(biāo)
 FrameControl fc;//邊框控件
 #endregion
 #region Properties
 #endregion
 #region Methods
 /// <summary>
 /// 掛載事件
 /// </summary>
 private void AddEvents()
 {
  currentControl.MouseClick += new MouseEventHandler(MouseClick);
  currentControl.MouseDown += new MouseEventHandler(MouseDown);
  currentControl.MouseMove += new MouseEventHandler(MouseMove);
  currentControl.MouseUp += new MouseEventHandler(MouseUp);
 }
 /// <summary>
 /// 繪制拖拉時(shí)的黑色邊框
 /// </summary>
 public static void DrawDragBound(Control ctrl)
 {
  ctrl.Refresh();
  Graphics g = ctrl.CreateGraphics();
  int width = ctrl.Width;
  int height = ctrl.Height;
  Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
   new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
  g.DrawLines(new Pen(Color.Black), ps);
 } 
 #endregion
 #region Events
 /// <summary>
 /// 鼠標(biāo)單擊事件:用來顯示邊框
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 protected void MouseClick(object sender, MouseEventArgs e)
 {
  this.currentControl.Parent.Refresh();//刷新父容器,清除掉其他控件的邊框
  this.currentControl.BringToFront();
  fc = new FrameControl(this.currentControl);
  this.currentControl.Parent.Controls.Add(fc);
  fc.Visible = true;
  fc.Draw();
 }
 /// <summary>
 /// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
 /// </summary>
 void MouseDown(object sender, MouseEventArgs e)
 {
  pPoint = Cursor.Position;
 }
 /// <summary>
 /// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
 /// </summary>
 void MouseMove(object sender, MouseEventArgs e)
 {
  Cursor.Current = Cursors.SizeAll; //當(dāng)鼠標(biāo)處于控件內(nèi)部時(shí),顯示光標(biāo)樣式為SizeAll
  //當(dāng)鼠標(biāo)左鍵按下時(shí)才觸發(fā)
  if (e.Button == MouseButtons.Left)
  {
   MoveControl.DrawDragBound(this.currentControl);
   if (fc != null) fc.Visible = false; //先隱藏
   cPoint = Cursor.Position; //獲得當(dāng)前鼠標(biāo)位置
   int x = cPoint.X - pPoint.X;
   int y = cPoint.Y - pPoint.Y;
   currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
   pPoint = cPoint;
  }
 }
 /// <summary>
 /// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
 /// </summary>
 void MouseUp(object sender, MouseEventArgs e)
 {
  this.currentControl.Refresh();
  if (fc != null)
  {
   fc.Visible = true;
   fc.Draw();
  }
 }
 #endregion
}
}

FrameControl

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace DragControl
{
 public partial class FrameControl : UserControl
 {
  #region Constructors
  public FrameControl(Control ctrl)
  {
   baseControl = ctrl;
   AddEvents();
   CreateBounds();
  }
  #endregion
  #region Fields
  const int Band = 6; //調(diào)整大小的響應(yīng)邊框
  Size square = new Size(Band, Band);//小矩形大小
  Control baseControl; //基礎(chǔ)控件,即被包圍的控件
  Rectangle[] smallRects = new Rectangle[8];//邊框中的八個(gè)小圓圈
  Rectangle[] sideRects = new Rectangle[4];//四條邊框,用來做響應(yīng)區(qū)域
  Point[] linePoints = new Point[5];//四條邊,用于畫虛線
  Graphics g; //畫圖板
  Rectangle ControlRect; //控件包含邊框的區(qū)域
  #endregion
  #region Methods
  /// <summary>
  /// 加載事件
  /// </summary>
  private void AddEvents()
  {
   this.Name = "FrameControl" + baseControl.Name;
   this.MouseDown += new MouseEventHandler(FrameControl_MouseDown);
   this.MouseMove += new MouseEventHandler(FrameControl_MouseMove);
   this.MouseUp += new MouseEventHandler(FrameControl_MouseUp);
  }
  #region 創(chuàng)建邊框
  /// <summary>
  /// 建立控件可視區(qū)域
  /// </summary>
  private void CreateBounds()
  {
   //創(chuàng)建邊界
   int X = baseControl.Bounds.X - square.Width - 1;
   int Y = baseControl.Bounds.Y - square.Height - 1;
   int Height = baseControl.Bounds.Height + (square.Height * 2) + 2;
   int Width = baseControl.Bounds.Width + (square.Width * 2) + 2;
   this.Bounds = new Rectangle(X, Y, Width, Height);
   this.BringToFront();
   SetRectangles();
   //設(shè)置可視區(qū)域
   this.Region = new Region(BuildFrame());
   g = this.CreateGraphics();
  }
  /// <summary>
  /// 設(shè)置定義8個(gè)小矩形的范圍
  /// </summary>
  void SetRectangles()
  {
   //左上
   smallRects[0] = new Rectangle(new Point(0, 0), square);
   //右上
   smallRects[1] = new Rectangle(new Point(this.Width - square.Width - 1, 0), square);
   //左下
   smallRects[2] = new Rectangle(new Point(0, this.Height - square.Height - 1), square);
   //右下
   smallRects[3] = new Rectangle(new Point(this.Width - square.Width - 1, this.Height - square.Height - 1), square);
   //上中
   smallRects[4] = new Rectangle(new Point(this.Width / 2 - 1, 0), square);
   //下中
   smallRects[5] = new Rectangle(new Point(this.Width / 2 - 1, this.Height - square.Height - 1), square);
   //左中
   smallRects[6] = new Rectangle(new Point(0, this.Height / 2 - 1), square);
   //右中
   smallRects[7] = new Rectangle(new Point(square.Width + baseControl.Width + 1, this.Height / 2 - 1), square);
   //四條邊線
   //左上
   linePoints[0] = new Point(square.Width / 2, square.Height / 2);
   //右上
   linePoints[1] = new Point(this.Width - square.Width / 2 - 1, square.Height / 2);
   //右下
   linePoints[2] = new Point(this.Width - square.Width / 2 - 1, this.Height - square.Height / 2);
   //左下
   linePoints[3] = new Point(square.Width / 2, this.Height - square.Height / 2 - 1);
   //左上
   linePoints[4] = new Point(square.Width / 2, square.Height / 2);
   //整個(gè)包括周圍邊框的范圍
   ControlRect = new Rectangle(new Point(0, 0), this.Bounds.Size);
  }
  /// <summary>
  /// 設(shè)置邊框控件可視區(qū)域
  /// </summary>
  /// <returns></returns>
  private GraphicsPath BuildFrame()
  {
   GraphicsPath path = new GraphicsPath();
   //上邊框
   sideRects[0] = new Rectangle(0, 0, this.Width - square.Width - 1, square.Height + 1);
   //左邊框
   sideRects[1] = new Rectangle(0, square.Height + 1, square.Width + 1, this.Height - square.Height - 1);
   //下邊框
   sideRects[2] = new Rectangle(square.Width + 1, this.Height - square.Height - 1, this.Width - square.Width - 1, square.Height + 1);
   //右邊框
   sideRects[3] = new Rectangle(this.Width - square.Width - 1, 0, square.Width + 1, this.Height - square.Height - 1);
   path.AddRectangle(sideRects[0]);
   path.AddRectangle(sideRects[1]);
   path.AddRectangle(sideRects[2]);
   path.AddRectangle(sideRects[3]);
   return path;
  }
  #endregion
  /// <summary>
  /// 繪圖
  /// </summary>
  public void Draw()
  {
   this.BringToFront();
   Pen pen = new Pen(Color.Black);
   pen.DashStyle = DashStyle.Dot;//設(shè)置為虛線,用虛線畫四邊,模擬微軟效果
   g.DrawLines(pen, linePoints);//繪制四條邊線
   g.FillRectangles(Brushes.White, smallRects); //填充8個(gè)小矩形的內(nèi)部
   foreach (Rectangle smallRect in smallRects)
   {
    g.DrawEllipse(Pens.Black, smallRect); //繪制8個(gè)小橢圓
   }
   //g.DrawRectangles(Pens.Black, smallRects); //繪制8個(gè)小矩形的黑色邊線
  }
  #endregion
  #region Events
  /// <summary>
  /// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
  /// </summary>
  void FrameControl_MouseDown(object sender, MouseEventArgs e)
  {
  }
  /// <summary>
  /// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
  /// </summary>
  void FrameControl_MouseMove(object sender, MouseEventArgs e)
  {
  }
  /// <summary>
  /// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
  /// </summary>
  void FrameControl_MouseUp(object sender, MouseEventArgs e)
  {
  }
  #endregion
 }
}

測試界面:

C# 實(shí)現(xiàn)拖拉控件改變位置與大小的方法

到目前為止,還只是有邊框,下面將實(shí)現(xiàn)拖拉功能。

首先來實(shí)現(xiàn),當(dāng)鼠標(biāo)放在響應(yīng)區(qū)域的時(shí)候,根據(jù)不同的位置顯示不同的箭頭樣子。

為此先創(chuàng)建一個(gè)枚舉,用來記錄當(dāng)前鼠標(biāo)的位置,等拖拉的時(shí)候根據(jù)該枚舉值做不同的計(jì)算。

/// <summary>
/// 鼠標(biāo)在控件中位置
/// </summary>
enum MousePosOnCtrl
{
 NONE = 0,
 TOP = 1,
 RIGHT = 2,
 BOTTOM = 3,
 LEFT = 4,
 TOPLEFT = 5,
 TOPRIGHT = 6,
 BOTTOMLEFT = 7,
 BOTTOMRIGHT = 8,
}

創(chuàng)建一個(gè)方法,用來改變光標(biāo)的樣子以及枚舉值

/// <summary>
/// 設(shè)置光標(biāo)狀態(tài)
/// </summary>
public bool SetCursorShape(int x, int y)
{
 Point point = new Point(x, y);
 if (!ControlRect.Contains(point))
 {
  Cursor.Current = Cursors.Arrow;
  return false;
 }
 else if (smallRects[0].Contains(point))
 {
  Cursor.Current = Cursors.SizeNWSE;
  mpoc = MousePosOnCtrl.TOPLEFT;
 }
 else if (smallRects[1].Contains(point))
 {
  Cursor.Current = Cursors.SizeNESW;
  mpoc = MousePosOnCtrl.TOPRIGHT;
 }
 else if (smallRects[2].Contains(point))
 {
  Cursor.Current = Cursors.SizeNESW;
  mpoc = MousePosOnCtrl.BOTTOMLEFT;
 }
 else if (smallRects[3].Contains(point))
 {
  Cursor.Current = Cursors.SizeNWSE;
  mpoc = MousePosOnCtrl.BOTTOMRIGHT;
 }
 else if (sideRects[0].Contains(point))
 {
  Cursor.Current = Cursors.SizeNS;
  mpoc = MousePosOnCtrl.TOP;
 }
 else if (sideRects[1].Contains(point))
 {
  Cursor.Current = Cursors.SizeWE;
  mpoc = MousePosOnCtrl.LEFT;
 }
 else if (sideRects[2].Contains(point))
 {
  Cursor.Current = Cursors.SizeNS;
  mpoc = MousePosOnCtrl.BOTTOM;
 }
 else if (sideRects[3].Contains(point))
 {
  Cursor.Current = Cursors.SizeWE;
  mpoc = MousePosOnCtrl.RIGHT;
 }
 else
 {
  Cursor.Current = Cursors.Arrow;
 }
 return true;
}

接著就是處理相關(guān)的三大事件MouseDown、MouseMove、MouseUp來實(shí)現(xiàn)拖拉。如同MoveControl都要增加以下兩個(gè)字段。

private Point pPoint; //上個(gè)鼠標(biāo)坐標(biāo)
private Point cPoint; //當(dāng)前鼠標(biāo)坐標(biāo)
/// <summary>
 /// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
 /// </summary>
 void FrameControl_MouseDown(object sender, MouseEventArgs e)
 {
  pPoint = Cursor.Position;
 }
 /// <summary>
/// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
/// </summary>
void FrameControl_MouseMove(object sender, MouseEventArgs e)
{
 if (e.Button == MouseButtons.Left)
 {
  this.Visible = false;
  MoveControl.DrawDragBound(baseControl);
  ControlMove();
 }
 else
 {
  this.Visible = true;
  SetCursorShape(e.X, e.Y); //更新鼠標(biāo)指針樣式
 }
}
/// <summary>
/// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
/// </summary>
void FrameControl_MouseUp(object sender, MouseEventArgs e)
{
 this.baseControl.Refresh(); //刷掉黑色邊框
 this.Visible = true;
 CreateBounds();
 Draw();
}

在上面的MouseMove中多了一個(gè)方法--ControlMove,這個(gè)就是根據(jù)不同的枚舉值,計(jì)算控件的移動(dòng)方式和大小的方法。該方法中同時(shí)對(duì)控件的最小寬度和高度做了處理。添加如下兩個(gè)字段。

private int MinWidth = 20; //最小寬度
private int MinHeight = 20;//最小高度
 /// <summary>
 /// 控件移動(dòng)
 /// </summary>
 private void ControlMove()
 {
  cPoint = Cursor.Position;
  int x = cPoint.X - pPoint.X;
  int y = cPoint.Y - pPoint.Y;
  switch (this.mpoc)
  {
   case MousePosOnCtrl.TOP:
    if (baseControl.Height - y > MinHeight)
    {
     baseControl.Top += y;
     baseControl.Height -= y;
    }
    else
    {
     baseControl.Top -= MinHeight - baseControl.Height;
     baseControl.Height = MinHeight;
    }
    break;
   case MousePosOnCtrl.BOTTOM:
    if (baseControl.Height + y > MinHeight)
    {
     baseControl.Height += y;
    }
    else
    {
     baseControl.Height = MinHeight;
    }
    break;
   case MousePosOnCtrl.LEFT:
    if (baseControl.Width - x > MinWidth)
    {
     baseControl.Left += x;
     baseControl.Width -= x;
    }
    else
    {
     baseControl.Left -= MinWidth - baseControl.Width;
     baseControl.Width = MinWidth;
    }
    break;
   case MousePosOnCtrl.RIGHT:
    if (baseControl.Width + x > MinWidth)
    {
     baseControl.Width += x;
    }
    else
    {
     baseControl.Width = MinWidth;
    }
    break;
   case MousePosOnCtrl.TOPLEFT:
    if (baseControl.Height - y > MinHeight)
    {
     baseControl.Top += y;
     baseControl.Height -= y;
    }
    else
    {
     baseControl.Top -= MinHeight - baseControl.Height;
     baseControl.Height = MinHeight;
    }
    if (baseControl.Width - x > MinWidth)
    {
     baseControl.Left += x;
     baseControl.Width -= x;
    }
    else
    {
     baseControl.Left -= MinWidth - baseControl.Width;
     baseControl.Width = MinWidth;
    }
    break;
   case MousePosOnCtrl.TOPRIGHT:
    if (baseControl.Height - y > MinHeight)
    {
     baseControl.Top += y;
     baseControl.Height -= y;
    }
    else
    {
     baseControl.Top -= MinHeight - baseControl.Height;
     baseControl.Height = MinHeight;
    }
    if (baseControl.Width + x > MinWidth)
    {
     baseControl.Width += x;
    }
    else
    {
     baseControl.Width = MinWidth;
    }
    break;
   case MousePosOnCtrl.BOTTOMLEFT:
    if (baseControl.Height + y > MinHeight)
   {
    baseControl.Height += y;
   }
   else
   {
    baseControl.Height = MinHeight;
   }
   if (baseControl.Width - x > MinWidth)
   {
    baseControl.Left += x;
    baseControl.Width -= x;
   }
   else
   {
    baseControl.Left -= MinWidth - baseControl.Width;
    baseControl.Width = MinWidth;
   }
   break;
  case MousePosOnCtrl.BOTTOMRIGHT:
   if (baseControl.Height + y > MinHeight)
   {
    baseControl.Height += y;
   }
   else
   {
    baseControl.Height = MinHeight;
   }
   if (baseControl.Width + x > MinWidth)
   {
    baseControl.Width += x;
   }
   else
   {
    baseControl.Width = MinWidth;
   }
   break;
 }
 pPoint = Cursor.Position;
} 

到此為止,功能已經(jīng)基本上實(shí)現(xiàn)。

完成代碼如下:

MoveControl

/******************************************************************
* 創(chuàng) 建 人: SamWang
* 創(chuàng)建時(shí)間: 2012-5-10 16:06
* 描 述:
*    移動(dòng)控件但不改變大小
* 原 理:
* 版 本: V1.0  
* 環(huán) 境: VS2010
******************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace DragControl
{
public class MoveControl
{
 #region Constructors
 public MoveControl(Control ctrl)
 {
  currentControl = ctrl;
  AddEvents();
 }
 #endregion
 #region Fields
 private Control currentControl; //傳入的控件
 private Point pPoint; //上個(gè)鼠標(biāo)坐標(biāo)
 private Point cPoint; //當(dāng)前鼠標(biāo)坐標(biāo)
 FrameControl fc;//邊框控件
 #endregion
 #region Properties
 #endregion
 #region Methods
 /// <summary>
 /// 掛載事件
 /// </summary>
 private void AddEvents()
 {
  currentControl.MouseClick += new MouseEventHandler(MouseClick);
  currentControl.MouseDown += new MouseEventHandler(MouseDown);
  currentControl.MouseMove += new MouseEventHandler(MouseMove);
  currentControl.MouseUp += new MouseEventHandler(MouseUp);
 }
 /// <summary>
 /// 繪制拖拉時(shí)的黑色邊框
 /// </summary>
 public static void DrawDragBound(Control ctrl)
 {
  ctrl.Refresh();
  Graphics g = ctrl.CreateGraphics();
  int width = ctrl.Width;
  int height = ctrl.Height;
  Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
   new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
  g.DrawLines(new Pen(Color.Black), ps);
 } 
 #endregion
 #region Events
 /// <summary>
 /// 鼠標(biāo)單擊事件:用來顯示邊框
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 protected void MouseClick(object sender, MouseEventArgs e)
 {
  this.currentControl.Parent.Refresh();//刷新父容器,清除掉其他控件的邊框
  this.currentControl.BringToFront();
  fc = new FrameControl(this.currentControl);
  this.currentControl.Parent.Controls.Add(fc);
  fc.Visible = true;
  fc.Draw();
 }
 /// <summary>
 /// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
 /// </summary>
 void MouseDown(object sender, MouseEventArgs e)
 {   
  pPoint = Cursor.Position;    
 }
 /// <summary>
 /// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
 /// </summary>
 void MouseMove(object sender, MouseEventArgs e)
 {
  Cursor.Current = Cursors.SizeAll; //當(dāng)鼠標(biāo)處于控件內(nèi)部時(shí),顯示光標(biāo)樣式為SizeAll
  //當(dāng)鼠標(biāo)左鍵按下時(shí)才觸發(fā)
  if (e.Button == MouseButtons.Left)
 {
  MoveControl.DrawDragBound(this.currentControl);
  if(fc != null ) fc.Visible = false; //先隱藏
  cPoint = Cursor.Position;//獲得當(dāng)前鼠標(biāo)位置
  int x = cPoint.X - pPoint.X;
  int y = cPoint.Y - pPoint.Y;
  currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
  pPoint = cPoint;
 }
}
/// <summary>
/// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
/// </summary>
void MouseUp(object sender, MouseEventArgs e)
{
 this.currentControl.Refresh();
 if (fc != null)
 {
  fc.Visible = true;
  fc.Draw();
 }
}
#endregion
}
}

FrameControl

/******************************************************************
* 創(chuàng) 建 人: SamWang
* 創(chuàng)建時(shí)間: 2012-5-10 17:00
* 描 述:
*    在控件外部加上邊框,用于拖拉,以改變內(nèi)部控件的大小
* 原 理:
* 版 本: V1.0  
* 環(huán) 境: VS2010
******************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DragControl
{
public class FrameControl : UserControl
{
 #region Constructors
 /// <summary>
 /// 構(gòu)造函數(shù)
 /// </summary>
 public FrameControl(Control ctrl)
 {
  baseControl = ctrl;
  AddEvents();
  CreateBounds();
 }
 #endregion
 #region Fields
 const int Band = 6; //調(diào)整大小的響應(yīng)邊框
 private int MinWidth = 20; //最小寬度
 private int MinHeight = 20;//最小高度
 Size square = new Size(Band, Band);//小矩形大小
 Control baseControl; //基礎(chǔ)控件,即被包圍的控件
 Rectangle[] smallRects = new Rectangle[8];//邊框中的八個(gè)小圓圈
 Rectangle[] sideRects = new Rectangle[4];//四條邊框,用來做響應(yīng)區(qū)域
 Point[] linePoints = new Point[5];//四條邊,用于畫虛線
 Graphics g; //畫圖板
 Rectangle ControlRect; //控件包含邊框的區(qū)域 
 private Point pPoint; //上個(gè)鼠標(biāo)坐標(biāo)
 private Point cPoint; //當(dāng)前鼠標(biāo)坐標(biāo)
 private MousePosOnCtrl mpoc;
 #endregion
 #region Properties
 /// <summary>
 /// 鼠標(biāo)在控件中位置
 /// </summary>
 enum MousePosOnCtrl
 {
  NONE = 0,
  TOP = 1,
  RIGHT = 2,
  BOTTOM = 3,
  LEFT = 4,
  TOPLEFT = 5,
  TOPRIGHT = 6,
  BOTTOMLEFT = 7,
  BOTTOMRIGHT = 8,
 }
 #endregion
 #region Methods
 /// <summary>
 /// 加載事件
 /// </summary>
 private void AddEvents()
 {
  this.Name = "FrameControl" + baseControl.Name;
  this.MouseDown += new MouseEventHandler(FrameControl_MouseDown);
  this.MouseMove += new MouseEventHandler(FrameControl_MouseMove);
  this.MouseUp += new MouseEventHandler(FrameControl_MouseUp);
 }
 #region 創(chuàng)建邊框
 /// <summary>
 /// 建立控件可視區(qū)域
 /// </summary>
 private void CreateBounds()
 {
  //創(chuàng)建邊界
  int X = baseControl.Bounds.X - square.Width - 1;
  int Y = baseControl.Bounds.Y - square.Height - 1;
  int Height = baseControl.Bounds.Height + (square.Height * 2) + 2;
  int Width = baseControl.Bounds.Width + (square.Width * 2) + 2;
  this.Bounds = new Rectangle(X, Y, Width, Height);
  this.BringToFront();
  SetRectangles();
  //設(shè)置可視區(qū)域
  this.Region = new Region(BuildFrame());
  g = this.CreateGraphics();
 }
 /// <summary>
 /// 設(shè)置定義8個(gè)小矩形的范圍
/// </summary>
void SetRectangles()
{
 //左上
 smallRects[0] = new Rectangle(new Point(0, 0), square);
 //右上
 smallRects[1] = new Rectangle(new Point(this.Width - square.Width - 1, 0), square);
 //左下
 smallRects[2] = new Rectangle(new Point(0, this.Height - square.Height - 1), square);
 //右下
 smallRects[3] = new Rectangle(new Point(this.Width - square.Width - 1, this.Height - square.Height - 1), square);
 //上中
 smallRects[4] = new Rectangle(new Point(this.Width / 2 - 1, 0), square);
 //下中
 smallRects[5] = new Rectangle(new Point(this.Width / 2 - 1, this.Height - square.Height - 1), square);
 //左中
 smallRects[6] = new Rectangle(new Point(0, this.Height / 2 - 1), square);
 //右中
 smallRects[7] = new Rectangle(new Point(square.Width + baseControl.Width + 1, this.Height / 2 - 1), square);
 //四條邊線
 //左上
 linePoints[0] = new Point(square.Width / 2, square.Height / 2);
 //右上
 linePoints[1] = new Point(this.Width - square.Width / 2 - 1, square.Height / 2);
 //右下
 linePoints[2] = new Point(this.Width - square.Width / 2 - 1, this.Height - square.Height / 2);
 //左下
 linePoints[3] = new Point(square.Width / 2, this.Height - square.Height / 2 - 1);
 //左上
 linePoints[4] = new Point(square.Width / 2, square.Height / 2);
 //整個(gè)包括周圍邊框的范圍
 ControlRect = new Rectangle(new Point(0, 0), this.Bounds.Size);
}
/// <summary>
/// 設(shè)置邊框控件可視區(qū)域
/// </summary>
/// <returns></returns>
private GraphicsPath BuildFrame()
{
 GraphicsPath path = new GraphicsPath();
 //上邊框
 sideRects[0] = new Rectangle(0, 0, this.Width - square.Width - 1, square.Height + 1);
 //左邊框
 sideRects[1] = new Rectangle(0, square.Height + 1, square.Width + 1, this.Height - square.Height - 1);
 //下邊框
 sideRects[2] = new Rectangle(square.Width + 1, this.Height - square.Height - 1, this.Width - square.Width - 1, square.Height + 1);
 //右邊框
 sideRects[3] = new Rectangle(this.Width - square.Width - 1, 0, square.Width + 1, this.Height - square.Height - 1);
 path.AddRectangle(sideRects[0]);
 path.AddRectangle(sideRects[1]);
 path.AddRectangle(sideRects[2]);
 path.AddRectangle(sideRects[3]);
 return path;
}
#endregion
/// <summary>
/// 繪圖
/// </summary>
public void Draw()
{
 this.BringToFront();
 //g.FillRectangles(Brushes.LightGray, sideRects); //填充四條邊框的內(nèi)部
 Pen pen = new Pen(Color.Black);
 pen.DashStyle = DashStyle.Dot;//設(shè)置為虛線,用虛線畫四邊,模擬微軟效果
 g.DrawLines(pen, linePoints);//繪制四條邊線
 g.FillRectangles(Brushes.White, smallRects); //填充8個(gè)小矩形的內(nèi)部
 foreach (Rectangle smallRect in smallRects)
 {
  g.DrawEllipse(Pens.Black, smallRect); //繪制8個(gè)小橢圓
 }
 //g.DrawRectangles(Pens.Black, smallRects); //繪制8個(gè)小矩形的黑色邊線
}
/// <summary>
/// 設(shè)置光標(biāo)狀態(tài)
/// </summary>
public bool SetCursorShape(int x, int y)
{
 Point point = new Point(x, y);
 if (!ControlRect.Contains(point))
 {
  Cursor.Current = Cursors.Arrow;
  return false;
 }
 else if (smallRects[0].Contains(point))
 {
  Cursor.Current = Cursors.SizeNWSE;
  mpoc = MousePosOnCtrl.TOPLEFT;
 }
 else if (smallRects[1].Contains(point))
 {
  Cursor.Current = Cursors.SizeNESW;
  mpoc = MousePosOnCtrl.TOPRIGHT;
 }
 else if (smallRects[2].Contains(point))
 {
  Cursor.Current = Cursors.SizeNESW;
  mpoc = MousePosOnCtrl.BOTTOMLEFT;
 }
 else if (smallRects[3].Contains(point))
 {
  Cursor.Current = Cursors.SizeNWSE;
  mpoc = MousePosOnCtrl.BOTTOMRIGHT;
 }
 else if (sideRects[0].Contains(point))
 {
  Cursor.Current = Cursors.SizeNS;
  mpoc = MousePosOnCtrl.TOP;
 }
 else if (sideRects[1].Contains(point))
 {
  Cursor.Current = Cursors.SizeWE;
  mpoc = MousePosOnCtrl.LEFT;
 }
 else if (sideRects[2].Contains(point))
 {
  Cursor.Current = Cursors.SizeNS;
  mpoc = MousePosOnCtrl.BOTTOM;
 }
 else if (sideRects[3].Contains(point))
 {
  Cursor.Current = Cursors.SizeWE;
  mpoc = MousePosOnCtrl.RIGHT;
 }
 else
 {
  Cursor.Current = Cursors.Arrow;
 }
 return true;
}
/// <summary>
/// 控件移動(dòng)
/// </summary>
private void ControlMove()
{
 cPoint = Cursor.Position;
 int x = cPoint.X - pPoint.X;
 int y = cPoint.Y - pPoint.Y;
 switch (this.mpoc)
 {
  case MousePosOnCtrl.TOP:
   if (baseControl.Height - y > MinHeight)
   {
    baseControl.Top += y;
    baseControl.Height -= y;      
   }
   else
   {
    baseControl.Top -= MinHeight - baseControl.Height;
    baseControl.Height = MinHeight;
   }
   break;
  case MousePosOnCtrl.BOTTOM:
   if (baseControl.Height + y > MinHeight)
   {
    baseControl.Height += y;
   }
   else
   {
    baseControl.Height = MinHeight;
   }
   break;
  case MousePosOnCtrl.LEFT:
   if (baseControl.Width - x > MinWidth)
   {
    baseControl.Left += x;
    baseControl.Width -= x;      
   }
   else
   {
    baseControl.Left -= MinWidth - baseControl.Width;
    baseControl.Width = MinWidth;
   }
   
   break;
  case MousePosOnCtrl.RIGHT:
   if (baseControl.Width + x > MinWidth)
   {
    baseControl.Width += x;
   }
   else
   {
    baseControl.Width = MinWidth;
   }
   break;
  case MousePosOnCtrl.TOPLEFT:
   if (baseControl.Height - y > MinHeight)
   {
    baseControl.Top += y;
    baseControl.Height -= y;
   }
   else
   {
    baseControl.Top -= MinHeight - baseControl.Height;
    baseControl.Height = MinHeight;
   }
   if (baseControl.Width - x > MinWidth)
   {
    baseControl.Left += x;
    baseControl.Width -= x;
   }
   else
   {
    baseControl.Left -= MinWidth - baseControl.Width;
    baseControl.Width = MinWidth;
   }
   break;
  case MousePosOnCtrl.TOPRIGHT:
   if (baseControl.Height - y > MinHeight)
   {
    baseControl.Top += y;
    baseControl.Height -= y;
   }
   else
   {
    baseControl.Top -= MinHeight - baseControl.Height;
    baseControl.Height = MinHeight;
   }
   if (baseControl.Width + x > MinWidth)
   {
    baseControl.Width += x;
   }
   else
   {
    baseControl.Width = MinWidth;
   }
   break;    
  case MousePosOnCtrl.BOTTOMLEFT:
   if (baseControl.Height + y > MinHeight)
   {
    baseControl.Height += y;
   }
   else
   {
    baseControl.Height = MinHeight;
   }
   if (baseControl.Width - x > MinWidth)
   {
    baseControl.Left += x;
    baseControl.Width -= x;
   }
   else
   {
    baseControl.Left -= MinWidth - baseControl.Width;
    baseControl.Width = MinWidth;
   }
   break;
  case MousePosOnCtrl.BOTTOMRIGHT:
   if (baseControl.Height + y > MinHeight)
   {
    baseControl.Height += y;
   }
   else
   {
    baseControl.Height = MinHeight;
   }
   if (baseControl.Width + x > MinWidth)
   {
    baseControl.Width += x;
   }
   else
   {
    baseControl.Width = MinWidth;
   }
   break;
  
 }
 pPoint = Cursor.Position;
}  
#endregion
#region Events
/// <summary>
/// 鼠標(biāo)按下事件:記錄當(dāng)前鼠標(biāo)相對(duì)窗體的坐標(biāo)
/// </summary>
void FrameControl_MouseDown(object sender, MouseEventArgs e)
{
 pPoint = Cursor.Position;
}
/// <summary>
/// 鼠標(biāo)移動(dòng)事件:讓控件跟著鼠標(biāo)移動(dòng)
/// </summary>
void FrameControl_MouseMove(object sender, MouseEventArgs e)
{
 if (e.Button == MouseButtons.Left)
 {
  this.Visible = false;
  MoveControl.DrawDragBound(baseControl);
  ControlMove();
 }
 else
 {
  this.Visible = true;
  SetCursorShape(e.X, e.Y); //更新鼠標(biāo)指針樣式
 }
}
/// <summary>
/// 鼠標(biāo)彈起事件:讓自定義的邊框出現(xiàn)
/// </summary>
void FrameControl_MouseUp(object sender, MouseEventArgs e)
{
 this.baseControl.Refresh(); //刷掉黑色邊框
 this.Visible = true;
 CreateBounds();
 Draw();
}
#endregion
}
}

四、遺留問題

1.ListBox存在拖拉高度時(shí),存在莫名奇妙的BUG。

2.目前該版本只支持單控件的拖拉,多控件同時(shí)拖拉等下次有空再弄。

以上這篇C# 實(shí)現(xiàn)拖拉控件改變位置與大小的方法就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持億速云。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI