前言:
很多時候我們需要在運行時,動態地改變控件的位置以及大小,以獲得更好的布局。比如說實際項目中的可自定義的報表、可自定義的單據等諸如此類。它們有個特點就是允許客戶或者二次開發人員設計它們需要的界面設置功能。
本人以前也做過可自定義系統,包括界面和功能,主要為了減少開發人員的工作量以及程序的靈活性和健壯性。
本篇主要討論下,在運行時如何實現拖拉控件,達到改變控件位置與大小。功能將模擬VS設計界面時的拖拉功能。
(本篇暫不涉及多控件同時操作)
一、技術概述
其實實現運行時控件的拖拉並不難,主要是改變控件的Location與Size即可。動態調整時再捕獲MouseDown、MouseMove及MouseUp事件來實時修改上述兩個屬性就可以實現。
二、功能規劃
在此之前,我們先來看下.net設計界面,一旦選中某個控件時,將會出現如下圖的邊框:
之後就可以通過拖拉出現的邊框改變其大小。而改變控件的位置,實際上是當鼠標點擊在控件內部拖動時實現的。
所有本例也將功能分為兩個部分實現,分別為控件內部拖動改變位置與控件邊框拖拉改變大小。
三、具體實現
1.拖動控件改變位置
首先,新建一個項目,然後添加一個類,取名叫MoveControl,該類用來給控件掛載事件實現拖動。
接著在該類中添加字段currentControl,用來保存需要操作的控件,即通過構造函數傳遞的控件。
接著創建一方法--AddEvents,用來給當前的控件掛載事件。
代碼如下:
DragControl
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Windows.Forms;
5 using System.Drawing;
6
7 namespace DragControl
8 {
9 public class MoveControl
10 {
11 #region Constructors
12 public MoveControl(Control ctrl)
13 {
14 currentControl = ctrl;
15 AddEvents();
16 }
17 #endregion
18
19 #region Fields
20 private Control currentControl; //傳入的控件
21 #endregion
22
23 #region Properties
24
25 #endregion
26
27 #region Methods
28 /// <summary>
29 /// 掛載事件
30 /// </summary>
31 private void AddEvents()
32 {
33 currentControl.MouseClick += new MouseEventHandler(MouseClick);
34 currentControl.MouseDown += new MouseEventHandler(MouseDown);
35 currentControl.MouseMove += new MouseEventHandler(MouseMove);
36 currentControl.MouseUp += new MouseEventHandler(MouseUp);
37 }
38 #endregion
39
40 #region Events
41 /// <summary>
42 /// 鼠標單擊事件:用來顯示邊框
43 /// </summary>
44 /// <param name="sender"></param>
45 /// <param name="e"></param>
46 void MouseClick(object sender, MouseEventArgs e)
47 {
48 }
49
50 /// <summary>
51 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
52 /// </summary>
53 void MouseDown(object sender, MouseEventArgs e)
54 {
55
56 }
57
58 /// <summary>
59 /// 鼠標移動事件:讓控件跟著鼠標移動
60 /// </summary>
61 void MouseMove(object sender, MouseEventArgs e)
62 {
63 }
64
65 /// <summary>
66 /// 鼠標彈起事件:讓自定義的邊框出現
67 /// </summary>
68 void MouseUp(object sender, MouseEventArgs e)
69 {
70 }
71 #endregion
72 }
73 }
接著我們需要實現MouseDown、MouseMove、MouseUp三個事件。
不過在此之前,我們必須要弄清楚,移動即表示坐標的改變,所以必定要有個起始坐標和終點坐標。
所以我們在MoveControl類中加入兩個字段。
private Point pPoint; //上個鼠標坐標
private Point cPoint; //當前鼠標坐標
而且在開始拖動之前,我們肯定需要先單擊一次控件。在MouseDown時獲取當前光標的位置,保存到pPoint中。
(此處用Cursor獲得坐標的好處,就是忽略掉容器的麻煩問題)
1 /// <summary>
2 /// 鼠標單擊事件:用來顯示邊框
3 /// </summary>
4 void MouseClick(object sender, MouseEventArgs e)
5 {
6 pPoint = Cursor.Position;
7 }
接著便實現MouseMove的事件,當鼠標左鍵按下時,接著移動鼠標後,繼續鼠標移動後的坐標,然後與MouseDown時記下的坐標相減,就得到鼠標的位移值,接著控件的Location加上該位移值即可,然後更新pPoint。
1 /// <summary>
2 /// 鼠標移動事件:讓控件跟著鼠標移動
3 /// </summary>
4 void MouseMove(object sender, MouseEventArgs e)
5 {
6 Cursor.Current = Cursors.SizeAll; //當鼠標處於控件內部時,顯示光標樣式為SizeAll
7 //當鼠標左鍵按下時才觸發
8 if (e.Button == MouseButtons.Left)
9 {
10 cPoint = Cursor.Position; //獲得當前鼠標位置
11 int x = cPoint.X - pPoint.X;
12 int y = cPoint.Y - pPoint.Y;
13 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
14 pPoint = cPoint;
15 }
16 }
由於此時還沒涉及到邊框,所以MouseUp暫時不用處理。至此拖動的基本功能已經實現!
目前MoveControl的完整代碼如下:
MoveControl
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Windows.Forms;
5 using System.Drawing;
6
7 namespace DragControl
8 {
9 public class MoveControl
10 {
11 #region Constructors
12 public MoveControl(Control ctrl)
13 {
14 currentControl = ctrl;
15 AddEvents();
16 }
17 #endregion
18
19 #region Fields
20 private Control currentControl; //傳入的控件
21 private Point pPoint; //上個鼠標坐標
22 private Point cPoint; //當前鼠標坐標
23 #endregion
24
25 #region Properties
26
27 #endregion
28
29 #region Methods
30 /// <summary>
31 /// 掛載事件
32 /// </summary>
33 private void AddEvents()
34 {
35 currentControl.MouseDown += new MouseEventHandler(MouseDown);
36 currentControl.MouseMove += new MouseEventHandler(MouseMove);
37 currentControl.MouseUp += new MouseEventHandler(MouseUp);
38 }
39
40 /// <summary>
41 /// 繪制拖拉時的黑色邊框
42 /// </summary>
43 public static void DrawDragBound(Control ctrl)
44 {
45 ctrl.Refresh();
46 Graphics g = ctrl.CreateGraphics();
47 int width = ctrl.Width;
48 int height = ctrl.Height;
49 Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
50 new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
51 g.DrawLines(new Pen(Color.Black), ps);
52 }
53 #endregion
54
55 #region Events
56 /// <summary>
57 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
58 /// </summary>
59 void MouseDown(object sender, MouseEventArgs e)
60 {
61 pPoint = Cursor.Position;
62 }
63
64 /// <summary>
65 /// 鼠標移動事件:讓控件跟著鼠標移動
66 /// </summary>
67 void MouseMove(object sender, MouseEventArgs e)
68 {
69 Cursor.Current = Cursors.SizeAll; //當鼠標處於控件內部時,顯示光標樣式為SizeAll
70 //當鼠標左鍵按下時才觸發
71 if (e.Button == MouseButtons.Left)
72 {
73 MoveControl.DrawDragBound(this.currentControl);
74 cPoint = Cursor.Position; //獲得當前鼠標位置
75 int x = cPoint.X - pPoint.X;
76 int y = cPoint.Y - pPoint.Y;
77 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
78 pPoint = cPoint;
79 }
80 }
81
82 /// <summary>
83 /// 鼠標彈起事件:讓自定義的邊框出現
84 /// </summary>
85 void MouseUp(object sender, MouseEventArgs e)
86 {
87 this.currentControl.Refresh();
88 }
89 #endregion
90 }
91 }
下面我們來測試下拖動的功能。
創建一個Form窗體,可以再界面上添加你要測試的控件類型,此處我只用TextBox左下測試。在Load的中添加以下代碼,將Form中的所有控件掛載上拖拉功能。
1 private void Form1_Load(object sender, EventArgs e)
2 {
3 foreach (Control ctrl in this.Controls)
4 {
5 new MoveControl(ctrl);
6 }
7 }
此時,有心人可能會發現VS中拖動控件時,將會出現黑色邊框,而處於沒有。
這也很簡單,我們在MouseMove時加上如下代碼即可。
1 /// <summary>
2 /// 繪制拖拉時的黑色邊框
3 /// </summary>
4 public static void DrawDragBound(Control ctrl)
5 {
6 ctrl.Refresh();
7 Graphics g = ctrl.CreateGraphics();
8 int width = ctrl.Width;
9 int height = ctrl.Height;
10 Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
11 new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
12 g.DrawLines(new Pen(Color.Black), ps);
13 }
14
15
16 /// <summary>
17 /// 鼠標移動事件:讓控件跟著鼠標移動
18 /// </summary>
19 void MouseMove(object sender, MouseEventArgs e)
20 {
21 Cursor.Current = Cursors.SizeAll; //當鼠標處於控件內部時,顯示光標樣式為SizeAll
22 //當鼠標左鍵按下時才觸發
23 if (e.Button == MouseButtons.Left)
24 {
25 MoveControl.DrawDragBound(this.currentControl);
26 cPoint = Cursor.Position; //獲得當前鼠標位置
27 int x = cPoint.X - pPoint.X;
28 int y = cPoint.Y - pPoint.Y;
29 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
30 pPoint = cPoint;
31 }
32 }
同時要在MoveUp的時候,刷新一下自己,讓黑色邊框消失掉!
1 /// <summary>
2 /// 鼠標彈起事件:讓自定義的邊框出現
3 /// </summary>
4 void MouseUp(object sender, MouseEventArgs e)
5 {
6 this.currentControl.Refresh();
7 }
接著用沒有邊框的控件測試下就會很明顯。如下圖所示:
2.通過邊框拖拉控件改變大小
此處的主要思路為:點擊控件的時候,創建一個自定義的用戶控件,該用戶控件響應區域就是傳入控件的邊框區域,同時給它畫上虛線與8個小圓圈。
第一、創建用戶控件--FrameControl(邊框控件),然後增加一個字段用來保存傳入的控件,還有加載事件,此處類同前面的MoveControl。
FrameControl
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Data;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9
10 namespace DragControl
11 {
12 public partial class FrameControl : UserControl
13 {
14 #region Constructors
15 public FrameControl(Control ctrl)
16 {
17 baseControl = ctrl;
18 AddEvents();
19 }
20 #endregion
21
22 #region Fields
23 Control baseControl; //基礎控件,即被包圍的控件
24 #endregion
25
26 #region Methods
27 /// <summary>
28 /// 加載事件
29 /// </summary>
30 private void AddEvents()
31 {
32 this.Name = "FrameControl" + baseControl.Name;
33 this.MouseDown += new MouseEventHandler(FrameControl_MouseDown);
34 this.MouseMove += new MouseEventHandler(FrameControl_MouseMove);
35 this.MouseUp += new MouseEventHandler(FrameControl_MouseUp);
36 }
37
38 #endregion
39
40 #region Events
41 /// <summary>
42 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
43 /// </summary>
44 void FrameControl_MouseDown(object sender, MouseEventArgs e)
45 {
46
47 }
48
49 /// <summary>
50 /// 鼠標移動事件:讓控件跟著鼠標移動
51 /// </summary>
52 void FrameControl_MouseMove(object sender, MouseEventArgs e)
53 {
54
55 }
56
57 /// <summary>
58 /// 鼠標彈起事件:讓自定義的邊框出現
59 /// </summary>
60 void FrameControl_MouseUp(object sender, MouseEventArgs e)
61 {
62
63 }
64 #endregion
65 }
66 }
做完這些准備工作後,將到了主要的部分,就是給控件畫邊框。
整個邊框分為三個部分:四邊框(用來設置可視區域與區域)+四條虛線(只用來顯示)+八個小圓圈(用來斜角拖拉)。
所以要建立三個字段,用來分別保存這個數據。
Rectangle[] smallRects = new Rectangle[8];//邊框中的八個小圓圈
Rectangle[] sideRects = new Rectangle[4];//四條邊框,用來做響應區域
Point[] linePoints = new Point[5];//四條邊,用於畫虛線
接著就是創建用戶控件的可視區域,和上面的三個變量數值。
(以下計算位置的代碼,有興趣的人可以研究下,沒有的就直接Copy)
創建邊框
1 #region 創建邊框
2 /// <summary>
3 /// 建立控件可視區域
4 /// </summary>
5 private void CreateBounds()
6 {
7 //創建邊界
8 int X = baseControl.Bounds.X - square.Width - 1;
9 int Y = baseControl.Bounds.Y - square.Height - 1;
10 int Height = baseControl.Bounds.Height + (square.Height * 2) + 2;
11 int Width = baseControl.Bounds.Width + (square.Width * 2) + 2;
12 this.Bounds = new Rectangle(X, Y, Width, Height);
13 this.BringToFront();
14 SetRectangles();
15 //設置可視區域
16 this.Region = new Region(BuildFrame());
17 g = this.CreateGraphics();
18 }
19
20 /// <summary>
21 /// 設置定義8個小矩形的范圍
22 /// </summary>
23 void SetRectangles()
24 {
25 //左上
26 smallRects[0] = new Rectangle(new Point(0, 0), square);
27 //右上
28 smallRects[1] = new Rectangle(new Point(this.Width - square.Width - 1, 0), square);
29 //左下
30 smallRects[2] = new Rectangle(new Point(0, this.Height - square.Height - 1), square);
31 //右下
32 smallRects[3] = new Rectangle(new Point(this.Width - square.Width - 1, this.Height - square.Height - 1), square);
33 //上中
34 smallRects[4] = new Rectangle(new Point(this.Width / 2 - 1, 0), square);
35 //下中
36 smallRects[5] = new Rectangle(new Point(this.Width / 2 - 1, this.Height - square.Height - 1), square);
37 //左中
38 smallRects[6] = new Rectangle(new Point(0, this.Height / 2 - 1), square);
39 //右中
40 smallRects[7] = new Rectangle(new Point(square.Width + baseControl.Width + 1, this.Height / 2 - 1), square);
41
42 //四條邊線
43 //左上
44 linePoints[0] = new Point(square.Width / 2, square.Height / 2);
45 //右上
46 linePoints[1] = new Point(this.Width - square.Width / 2 - 1, square.Height / 2);
47 //右下
48 linePoints[2] = new Point(this.Width - square.Width / 2 - 1, this.Height - square.Height / 2);
49 //左下
50 linePoints[3] = new Point(square.Width / 2, this.Height - square.Height / 2 - 1);
51 //左上
52 linePoints[4] = new Point(square.Width / 2, square.Height / 2);
53
54 //整個包括周圍邊框的范圍
55 ControlRect = new Rectangle(new Point(0, 0), this.Bounds.Size);
56 }
57
58 /// <summary>
59 /// 設置邊框控件可視區域
60 /// </summary>
61 /// <returns></returns>
62 private GraphicsPath BuildFrame()
63 {
64 GraphicsPath path = new GraphicsPath();
65 //上邊框
66 sideRects[0] = new Rectangle(0, 0, this.Width - square.Width - 1, square.Height + 1);
67 //左邊框
68 sideRects[1] = new Rectangle(0, square.Height + 1, square.Width + 1, this.Height - square.Height - 1);
69 //下邊框
70 sideRects[2] = new Rectangle(square.Width + 1, this.Height - square.Height - 1, this.Width - square.Width - 1, square.Height + 1);
71 //右邊框
72 sideRects[3] = new Rectangle(this.Width - square.Width - 1, 0, square.Width + 1, this.Height - square.Height - 1);
73
74 path.AddRectangle(sideRects[0]);
75 path.AddRectangle(sideRects[1]);
76 path.AddRectangle(sideRects[2]);
77 path.AddRectangle(sideRects[3]);
78 return path;
79 }
80 #endregion
設置完位置後,接著就是繪制的工作。增加一個Draw的方法用來畫,同時設置為Public。此處不用控件的Paint,而是讓用戶調用,只因為這樣方便在不同控件之間切換,也就是一個容器中,只有當前控件有邊框。
1 /// <summary>
2 /// 繪圖
3 /// </summary>
4 public void Draw()
5 {
6 this.BringToFront();
7 Pen pen = new Pen(Color.Black);
8 pen.DashStyle = DashStyle.Dot;//設置為虛線,用虛線畫四邊,模擬微軟效果
9 g.DrawLines(pen, linePoints);//繪制四條邊線
10 g.FillRectangles(Brushes.White, smallRects); //填充8個小矩形的內部
11 foreach (Rectangle smallRect in smallRects)
12 {
13 g.DrawEllipse(Pens.Black, smallRect); //繪制8個小橢圓
14 }
15 //g.DrawRectangles(Pens.Black, smallRects); //繪制8個小矩形的黑色邊線
16 }
做到這裡,我們可以去前台看一下效果,不過再此之前,我們需要調用該用戶控件。
調用的地方就是在控件上點擊的時候,所以在MoveControl中加入MouseClick的事件。
1 /// <summary>
2 /// 鼠標單擊事件:用來顯示邊框
3 /// </summary>
4 /// <param name="sender"></param>
5 /// <param name="e"></param>
6 protected void MouseClick(object sender, MouseEventArgs e)
7 {
8 this.currentControl.Parent.Refresh();//刷新父容器,清除掉其他控件的邊框
9 this.currentControl.BringToFront();
10 fc = new FrameControl(this.currentControl);
11 this.currentControl.Parent.Controls.Add(fc);
12 fc.Visible = true;
13 fc.Draw();
14 }
這時有了邊框之後會有一個小問題,就是拖動控件的時候,控件移動了,但是邊框還留在原地。
所以,這裡需要注意的,就是移動的時候,將邊框控件隱藏掉,當MouseUp的時候再顯示。
此時的完整代碼如下:
MoveControl
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Windows.Forms;
5 using System.Drawing;
6
7 namespace DragControl
8 {
9 public class MoveControl
10 {
11 #region Constructors
12 public MoveControl(Control ctrl)
13 {
14 currentControl = ctrl;
15 AddEvents();
16 }
17 #endregion
18
19 #region Fields
20 private Control currentControl; //傳入的控件
21 private Point pPoint; //上個鼠標坐標
22 private Point cPoint; //當前鼠標坐標
23 FrameControl fc;//邊框控件
24 #endregion
25
26 #region Properties
27
28 #endregion
29
30 #region Methods
31 /// <summary>
32 /// 掛載事件
33 /// </summary>
34 private void AddEvents()
35 {
36 currentControl.MouseClick += new MouseEventHandler(MouseClick);
37 currentControl.MouseDown += new MouseEventHandler(MouseDown);
38 currentControl.MouseMove += new MouseEventHandler(MouseMove);
39 currentControl.MouseUp += new MouseEventHandler(MouseUp);
40 }
41
42 /// <summary>
43 /// 繪制拖拉時的黑色邊框
44 /// </summary>
45 public static void DrawDragBound(Control ctrl)
46 {
47 ctrl.Refresh();
48 Graphics g = ctrl.CreateGraphics();
49 int width = ctrl.Width;
50 int height = ctrl.Height;
51 Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
52 new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
53 g.DrawLines(new Pen(Color.Black), ps);
54 }
55 #endregion
56
57 #region Events
58 /// <summary>
59 /// 鼠標單擊事件:用來顯示邊框
60 /// </summary>
61 /// <param name="sender"></param>
62 /// <param name="e"></param>
63 protected void MouseClick(object sender, MouseEventArgs e)
64 {
65 this.currentControl.Parent.Refresh();//刷新父容器,清除掉其他控件的邊框
66 this.currentControl.BringToFront();
67 fc = new FrameControl(this.currentControl);
68 this.currentControl.Parent.Controls.Add(fc);
69 fc.Visible = true;
70 fc.Draw();
71 }
72
73 /// <summary>
74 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
75 /// </summary>
76 void MouseDown(object sender, MouseEventArgs e)
77 {
78 pPoint = Cursor.Position;
79 }
80
81 /// <summary>
82 /// 鼠標移動事件:讓控件跟著鼠標移動
83 /// </summary>
84 void MouseMove(object sender, MouseEventArgs e)
85 {
86 Cursor.Current = Cursors.SizeAll; //當鼠標處於控件內部時,顯示光標樣式為SizeAll
87 //當鼠標左鍵按下時才觸發
88 if (e.Button == MouseButtons.Left)
89 {
90 MoveControl.DrawDragBound(this.currentControl);
91 if (fc != null) fc.Visible = false; //先隱藏
92 cPoint = Cursor.Position; //獲得當前鼠標位置
93 int x = cPoint.X - pPoint.X;
94 int y = cPoint.Y - pPoint.Y;
95 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
96 pPoint = cPoint;
97 }
98 }
99
100 /// <summary>
101 /// 鼠標彈起事件:讓自定義的邊框出現
102 /// </summary>
103 void MouseUp(object sender, MouseEventArgs e)
104 {
105 this.currentControl.Refresh();
106 if (fc != null)
107 {
108 fc.Visible = true;
109 fc.Draw();
110 }
111 }
112 #endregion
113 }
114 }
FrameControl
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Drawing;
5 using System.Data;
6 using System.Text;
7 using System.Windows.Forms;
8 using System.Drawing.Drawing2D;
9
10 namespace DragControl
11 {
12 public partial class FrameControl : UserControl
13 {
14 #region Constructors
15 public FrameControl(Control ctrl)
16 {
17 baseControl = ctrl;
18 AddEvents();
19 CreateBounds();
20 }
21 #endregion
22
23 #region Fields
24 const int Band = 6; //調整大小的響應邊框
25 Size square = new Size(Band, Band);//小矩形大小
26 Control baseControl; //基礎控件,即被包圍的控件
27 Rectangle[] smallRects = new Rectangle[8];//邊框中的八個小圓圈
28 Rectangle[] sideRects = new Rectangle[4];//四條邊框,用來做響應區域
29 Point[] linePoints = new Point[5];//四條邊,用於畫虛線
30 Graphics g; //畫圖板
31 Rectangle ControlRect; //控件包含邊框的區域
32 #endregion
33
34 #region Methods
35 /// <summary>
36 /// 加載事件
37 /// </summary>
38 private void AddEvents()
39 {
40 this.Name = "FrameControl" + baseControl.Name;
41 this.MouseDown += new MouseEventHandler(FrameControl_MouseDown);
42 this.MouseMove += new MouseEventHandler(FrameControl_MouseMove);
43 this.MouseUp += new MouseEventHandler(FrameControl_MouseUp);
44 }
45
46 #region 創建邊框
47 /// <summary>
48 /// 建立控件可視區域
49 /// </summary>
50 private void CreateBounds()
51 {
52 //創建邊界
53 int X = baseControl.Bounds.X - square.Width - 1;
54 int Y = baseControl.Bounds.Y - square.Height - 1;
55 int Height = baseControl.Bounds.Height + (square.Height * 2) + 2;
56 int Width = baseControl.Bounds.Width + (square.Width * 2) + 2;
57 this.Bounds = new Rectangle(X, Y, Width, Height);
58 this.BringToFront();
59 SetRectangles();
60 //設置可視區域
61 this.Region = new Region(BuildFrame());
62 g = this.CreateGraphics();
63 }
64
65 /// <summary>
66 /// 設置定義8個小矩形的范圍
67 /// </summary>
68 void SetRectangles()
69 {
70 //左上
71 smallRects[0] = new Rectangle(new Point(0, 0), square);
72 //右上
73 smallRects[1] = new Rectangle(new Point(this.Width - square.Width - 1, 0), square);
74 //左下
75 smallRects[2] = new Rectangle(new Point(0, this.Height - square.Height - 1), square);
76 //右下
77 smallRects[3] = new Rectangle(new Point(this.Width - square.Width - 1, this.Height - square.Height - 1), square);
78 //上中
79 smallRects[4] = new Rectangle(new Point(this.Width / 2 - 1, 0), square);
80 //下中
81 smallRects[5] = new Rectangle(new Point(this.Width / 2 - 1, this.Height - square.Height - 1), square);
82 //左中
83 smallRects[6] = new Rectangle(new Point(0, this.Height / 2 - 1), square);
84 //右中
85 smallRects[7] = new Rectangle(new Point(square.Width + baseControl.Width + 1, this.Height / 2 - 1), square);
86
87 //四條邊線
88 //左上
89 linePoints[0] = new Point(square.Width / 2, square.Height / 2);
90 //右上
91 linePoints[1] = new Point(this.Width - square.Width / 2 - 1, square.Height / 2);
92 //右下
93 linePoints[2] = new Point(this.Width - square.Width / 2 - 1, this.Height - square.Height / 2);
94 //左下
95 linePoints[3] = new Point(square.Width / 2, this.Height - square.Height / 2 - 1);
96 //左上
97 linePoints[4] = new Point(square.Width / 2, square.Height / 2);
98
99 //整個包括周圍邊框的范圍
100 ControlRect = new Rectangle(new Point(0, 0), this.Bounds.Size);
101 }
102
103 /// <summary>
104 /// 設置邊框控件可視區域
105 /// </summary>
106 /// <returns></returns>
107 private GraphicsPath BuildFrame()
108 {
109 GraphicsPath path = new GraphicsPath();
110 //上邊框
111 sideRects[0] = new Rectangle(0, 0, this.Width - square.Width - 1, square.Height + 1);
112 //左邊框
113 sideRects[1] = new Rectangle(0, square.Height + 1, square.Width + 1, this.Height - square.Height - 1);
114 //下邊框
115 sideRects[2] = new Rectangle(square.Width + 1, this.Height - square.Height - 1, this.Width - square.Width - 1, square.Height + 1);
116 //右邊框
117 sideRects[3] = new Rectangle(this.Width - square.Width - 1, 0, square.Width + 1, this.Height - square.Height - 1);
118
119 path.AddRectangle(sideRects[0]);
120 path.AddRectangle(sideRects[1]);
121 path.AddRectangle(sideRects[2]);
122 path.AddRectangle(sideRects[3]);
123 return path;
124 }
125 #endregion
126
127 /// <summary>
128 /// 繪圖
129 /// </summary>
130 public void Draw()
131 {
132 this.BringToFront();
133 Pen pen = new Pen(Color.Black);
134 pen.DashStyle = DashStyle.Dot;//設置為虛線,用虛線畫四邊,模擬微軟效果
135 g.DrawLines(pen, linePoints);//繪制四條邊線
136 g.FillRectangles(Brushes.White, smallRects); //填充8個小矩形的內部
137 foreach (Rectangle smallRect in smallRects)
138 {
139 g.DrawEllipse(Pens.Black, smallRect); //繪制8個小橢圓
140 }
141 //g.DrawRectangles(Pens.Black, smallRects); //繪制8個小矩形的黑色邊線
142 }
143
144 #endregion
145
146 #region Events
147 /// <summary>
148 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
149 /// </summary>
150 void FrameControl_MouseDown(object sender, MouseEventArgs e)
151 {
152
153 }
154
155 /// <summary>
156 /// 鼠標移動事件:讓控件跟著鼠標移動
157 /// </summary>
158 void FrameControl_MouseMove(object sender, MouseEventArgs e)
159 {
160
161 }
162
163 /// <summary>
164 /// 鼠標彈起事件:讓自定義的邊框出現
165 /// </summary>
166 void FrameControl_MouseUp(object sender, MouseEventArgs e)
167 {
168
169 }
170 #endregion
171 }
172 }
測試界面:
到目前為止,還只是有邊框,下面將實現拖拉功能。
首先來實現,當鼠標放在響應區域的時候,根據不同的位置顯示不同的箭頭樣子。
為此先創建一個枚舉,用來記錄當前鼠標的位置,等拖拉的時候根據該枚舉值做不同的計算。
1 /// <summary>
2 /// 鼠標在控件中位置
3 /// </summary>
4 enum MousePosOnCtrl
5 {
6 NONE = 0,
7 TOP = 1,
8 RIGHT = 2,
9 BOTTOM = 3,
10 LEFT = 4,
11 TOPLEFT = 5,
12 TOPRIGHT = 6,
13 BOTTOMLEFT = 7,
14 BOTTOMRIGHT = 8,
15 }
創建一個方法,用來改變光標的樣子以及枚舉值
1 /// <summary>
2 /// 設置光標狀態
3 /// </summary>
4 public bool SetCursorShape(int x, int y)
5 {
6 Point point = new Point(x, y);
7 if (!ControlRect.Contains(point))
8 {
9 Cursor.Current = Cursors.Arrow;
10 return false;
11 }
12 else if (smallRects[0].Contains(point))
13 {
14 Cursor.Current = Cursors.SizeNWSE;
15 mpoc = MousePosOnCtrl.TOPLEFT;
16 }
17 else if (smallRects[1].Contains(point))
18 {
19 Cursor.Current = Cursors.SizeNESW;
20 mpoc = MousePosOnCtrl.TOPRIGHT;
21 }
22 else if (smallRects[2].Contains(point))
23 {
24 Cursor.Current = Cursors.SizeNESW;
25 mpoc = MousePosOnCtrl.BOTTOMLEFT;
26 }
27 else if (smallRects[3].Contains(point))
28 {
29 Cursor.Current = Cursors.SizeNWSE;
30 mpoc = MousePosOnCtrl.BOTTOMRIGHT;
31 }
32 else if (sideRects[0].Contains(point))
33 {
34 Cursor.Current = Cursors.SizeNS;
35 mpoc = MousePosOnCtrl.TOP;
36 }
37 else if (sideRects[1].Contains(point))
38 {
39 Cursor.Current = Cursors.SizeWE;
40 mpoc = MousePosOnCtrl.LEFT;
41 }
42 else if (sideRects[2].Contains(point))
43 {
44 Cursor.Current = Cursors.SizeNS;
45 mpoc = MousePosOnCtrl.BOTTOM;
46 }
47 else if (sideRects[3].Contains(point))
48 {
49 Cursor.Current = Cursors.SizeWE;
50 mpoc = MousePosOnCtrl.RIGHT;
51 }
52 else
53 {
54 Cursor.Current = Cursors.Arrow;
55 }
56 return true;
57 }
接著就是處理相關的三大事件MouseDown、MouseMove、MouseUp來實現拖拉。如同MoveControl都要增加以下兩個字段。
private Point pPoint; //上個鼠標坐標
private Point cPoint; //當前鼠標坐標
1 /// <summary>
2 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
3 /// </summary>
4 void FrameControl_MouseDown(object sender, MouseEventArgs e)
5 {
6 pPoint = Cursor.Position;
7 }
8
9 /// <summary>
10 /// 鼠標移動事件:讓控件跟著鼠標移動
11 /// </summary>
12 void FrameControl_MouseMove(object sender, MouseEventArgs e)
13 {
14 if (e.Button == MouseButtons.Left)
15 {
16 this.Visible = false;
17 MoveControl.DrawDragBound(baseControl);
18 ControlMove();
19 }
20 else
21 {
22 this.Visible = true;
23 SetCursorShape(e.X, e.Y); //更新鼠標指針樣式
24 }
25 }
26
27 /// <summary>
28 /// 鼠標彈起事件:讓自定義的邊框出現
29 /// </summary>
30 void FrameControl_MouseUp(object sender, MouseEventArgs e)
31 {
32 this.baseControl.Refresh(); //刷掉黑色邊框
33 this.Visible = true;
34 CreateBounds();
35 Draw();
36 }
在上面的MouseMove中多了一個方法--ControlMove,這個就是根據不同的枚舉值,計算控件的移動方式和大小的方法。該方法中同時對控件的最小寬度和高度做了處理。添加如下兩個字段。
private int MinWidth = 20; //最小寬度
private int MinHeight = 20;//最小高度
1 /// <summary>
2 /// 控件移動
3 /// </summary>
4 private void ControlMove()
5 {
6 cPoint = Cursor.Position;
7 int x = cPoint.X - pPoint.X;
8 int y = cPoint.Y - pPoint.Y;
9 switch (this.mpoc)
10 {
11 case MousePosOnCtrl.TOP:
12 if (baseControl.Height - y > MinHeight)
13 {
14 baseControl.Top += y;
15 baseControl.Height -= y;
16 }
17 else
18 {
19 baseControl.Top -= MinHeight - baseControl.Height;
20 baseControl.Height = MinHeight;
21 }
22 break;
23 case MousePosOnCtrl.BOTTOM:
24 if (baseControl.Height + y > MinHeight)
25 {
26 baseControl.Height += y;
27 }
28 else
29 {
30 baseControl.Height = MinHeight;
31 }
32 break;
33 case MousePosOnCtrl.LEFT:
34 if (baseControl.Width - x > MinWidth)
35 {
36 baseControl.Left += x;
37 baseControl.Width -= x;
38 }
39 else
40 {
41 baseControl.Left -= MinWidth - baseControl.Width;
42 baseControl.Width = MinWidth;
43 }
44
45 break;
46 case MousePosOnCtrl.RIGHT:
47 if (baseControl.Width + x > MinWidth)
48 {
49 baseControl.Width += x;
50 }
51 else
52 {
53 baseControl.Width = MinWidth;
54 }
55 break;
56 case MousePosOnCtrl.TOPLEFT:
57 if (baseControl.Height - y > MinHeight)
58 {
59 baseControl.Top += y;
60 baseControl.Height -= y;
61 }
62 else
63 {
64 baseControl.Top -= MinHeight - baseControl.Height;
65 baseControl.Height = MinHeight;
66 }
67 if (baseControl.Width - x > MinWidth)
68 {
69 baseControl.Left += x;
70 baseControl.Width -= x;
71 }
72 else
73 {
74 baseControl.Left -= MinWidth - baseControl.Width;
75 baseControl.Width = MinWidth;
76 }
77 break;
78 case MousePosOnCtrl.TOPRIGHT:
79 if (baseControl.Height - y > MinHeight)
80 {
81 baseControl.Top += y;
82 baseControl.Height -= y;
83 }
84 else
85 {
86 baseControl.Top -= MinHeight - baseControl.Height;
87 baseControl.Height = MinHeight;
88 }
89 if (baseControl.Width + x > MinWidth)
90 {
91 baseControl.Width += x;
92 }
93 else
94 {
95 baseControl.Width = MinWidth;
96 }
97 break;
98 case MousePosOnCtrl.BOTTOMLEFT:
99 if (baseControl.Height + y > MinHeight)
100 {
101 baseControl.Height += y;
102 }
103 else
104 {
105 baseControl.Height = MinHeight;
106 }
107 if (baseControl.Width - x > MinWidth)
108 {
109 baseControl.Left += x;
110 baseControl.Width -= x;
111 }
112 else
113 {
114 baseControl.Left -= MinWidth - baseControl.Width;
115 baseControl.Width = MinWidth;
116 }
117 break;
118 case MousePosOnCtrl.BOTTOMRIGHT:
119 if (baseControl.Height + y > MinHeight)
120 {
121 baseControl.Height += y;
122 }
123 else
124 {
125 baseControl.Height = MinHeight;
126 }
127 if (baseControl.Width + x > MinWidth)
128 {
129 baseControl.Width += x;
130 }
131 else
132 {
133 baseControl.Width = MinWidth;
134 }
135 break;
136
137 }
138 pPoint = Cursor.Position;
139 }
到此為止,功能已經基本上實現。
完成代碼如下:
MoveControl
1 /******************************************************************
2 * 創 建 人: SamWang
3 * 創建時間: 2012-5-10 16:06
4 * 描 述:
5 * 移動控件但不改變大小
6 * 原 理:
7 * 版 本: V1.0
8 * 環 境: VS2010
9 ******************************************************************/
10 using System;
11 using System.Collections.Generic;
12 using System.Linq;
13 using System.Text;
14 using System.Windows.Forms;
15 using System.Drawing;
16
17 namespace DragControl
18 {
19 public class MoveControl
20 {
21 #region Constructors
22 public MoveControl(Control ctrl)
23 {
24 currentControl = ctrl;
25 AddEvents();
26 }
27 #endregion
28
29 #region Fields
30 private Control currentControl; //傳入的控件
31 private Point pPoint; //上個鼠標坐標
32 private Point cPoint; //當前鼠標坐標
33 FrameControl fc;//邊框控件
34 #endregion
35
36 #region Properties
37
38 #endregion
39
40 #region Methods
41 /// <summary>
42 /// 掛載事件
43 /// </summary>
44 private void AddEvents()
45 {
46 currentControl.MouseClick += new MouseEventHandler(MouseClick);
47 currentControl.MouseDown += new MouseEventHandler(MouseDown);
48 currentControl.MouseMove += new MouseEventHandler(MouseMove);
49 currentControl.MouseUp += new MouseEventHandler(MouseUp);
50 }
51
52 /// <summary>
53 /// 繪制拖拉時的黑色邊框
54 /// </summary>
55 public static void DrawDragBound(Control ctrl)
56 {
57 ctrl.Refresh();
58 Graphics g = ctrl.CreateGraphics();
59 int width = ctrl.Width;
60 int height = ctrl.Height;
61 Point[] ps = new Point[5]{new Point(0,0),new Point(width -1,0),
62 new Point(width -1,height -1),new Point(0,height-1),new Point(0,0)};
63 g.DrawLines(new Pen(Color.Black), ps);
64 }
65
66 #endregion
67
68 #region Events
69 /// <summary>
70 /// 鼠標單擊事件:用來顯示邊框
71 /// </summary>
72 /// <param name="sender"></param>
73 /// <param name="e"></param>
74 protected void MouseClick(object sender, MouseEventArgs e)
75 {
76 this.currentControl.Parent.Refresh();//刷新父容器,清除掉其他控件的邊框
77 this.currentControl.BringToFront();
78 fc = new FrameControl(this.currentControl);
79 this.currentControl.Parent.Controls.Add(fc);
80 fc.Visible = true;
81 fc.Draw();
82 }
83
84 /// <summary>
85 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
86 /// </summary>
87 void MouseDown(object sender, MouseEventArgs e)
88 {
89 pPoint = Cursor.Position;
90 }
91
92 /// <summary>
93 /// 鼠標移動事件:讓控件跟著鼠標移動
94 /// </summary>
95 void MouseMove(object sender, MouseEventArgs e)
96 {
97 Cursor.Current = Cursors.SizeAll; //當鼠標處於控件內部時,顯示光標樣式為SizeAll
98 //當鼠標左鍵按下時才觸發
99 if (e.Button == MouseButtons.Left)
100 {
101 MoveControl.DrawDragBound(this.currentControl);
102 if(fc != null ) fc.Visible = false; //先隱藏
103 cPoint = Cursor.Position;//獲得當前鼠標位置
104 int x = cPoint.X - pPoint.X;
105 int y = cPoint.Y - pPoint.Y;
106 currentControl.Location = new Point(currentControl.Location.X + x, currentControl.Location.Y + y);
107 pPoint = cPoint;
108 }
109 }
110
111 /// <summary>
112 /// 鼠標彈起事件:讓自定義的邊框出現
113 /// </summary>
114 void MouseUp(object sender, MouseEventArgs e)
115 {
116 this.currentControl.Refresh();
117 if (fc != null)
118 {
119 fc.Visible = true;
120 fc.Draw();
121 }
122 }
123 #endregion
124 }
125 }
FrameControl
1 /******************************************************************
2 * 創 建 人: SamWang
3 * 創建時間: 2012-5-10 17:00
4 * 描 述:
5 * 在控件外部加上邊框,用於拖拉,以改變內部控件的大小
6 * 原 理:
7 * 版 本: V1.0
8 * 環 境: VS2010
9 ******************************************************************/
10 using System;
11 using System.Collections.Generic;
12 using System.Text;
13 using System.Windows.Forms;
14 using System.Drawing;
15 using System.Drawing.Drawing2D;
16
17 namespace DragControl
18 {
19 public class FrameControl : UserControl
20 {
21 #region Constructors
22 /// <summary>
23 /// 構造函數
24 /// </summary>
25 public FrameControl(Control ctrl)
26 {
27 baseControl = ctrl;
28 AddEvents();
29 CreateBounds();
30 }
31 #endregion
32
33 #region Fields
34 const int Band = 6; //調整大小的響應邊框
35 private int MinWidth = 20; //最小寬度
36 private int MinHeight = 20;//最小高度
37 Size square = new Size(Band, Band);//小矩形大小
38 Control baseControl; //基礎控件,即被包圍的控件
39 Rectangle[] smallRects = new Rectangle[8];//邊框中的八個小圓圈
40 Rectangle[] sideRects = new Rectangle[4];//四條邊框,用來做響應區域
41 Point[] linePoints = new Point[5];//四條邊,用於畫虛線
42 Graphics g; //畫圖板
43 Rectangle ControlRect; //控件包含邊框的區域
44 private Point pPoint; //上個鼠標坐標
45 private Point cPoint; //當前鼠標坐標
46 private MousePosOnCtrl mpoc;
47 #endregion
48
49 #region Properties
50 /// <summary>
51 /// 鼠標在控件中位置
52 /// </summary>
53 enum MousePosOnCtrl
54 {
55 NONE = 0,
56 TOP = 1,
57 RIGHT = 2,
58 BOTTOM = 3,
59 LEFT = 4,
60 TOPLEFT = 5,
61 TOPRIGHT = 6,
62 BOTTOMLEFT = 7,
63 BOTTOMRIGHT = 8,
64 }
65 #endregion
66
67 #region Methods
68 /// <summary>
69 /// 加載事件
70 /// </summary>
71 private void AddEvents()
72 {
73 this.Name = "FrameControl" + baseControl.Name;
74 this.MouseDown += new MouseEventHandler(FrameControl_MouseDown);
75 this.MouseMove += new MouseEventHandler(FrameControl_MouseMove);
76 this.MouseUp += new MouseEventHandler(FrameControl_MouseUp);
77 }
78
79 #region 創建邊框
80 /// <summary>
81 /// 建立控件可視區域
82 /// </summary>
83 private void CreateBounds()
84 {
85 //創建邊界
86 int X = baseControl.Bounds.X - square.Width - 1;
87 int Y = baseControl.Bounds.Y - square.Height - 1;
88 int Height = baseControl.Bounds.Height + (square.Height * 2) + 2;
89 int Width = baseControl.Bounds.Width + (square.Width * 2) + 2;
90 this.Bounds = new Rectangle(X, Y, Width, Height);
91 this.BringToFront();
92 SetRectangles();
93 //設置可視區域
94 this.Region = new Region(BuildFrame());
95 g = this.CreateGraphics();
96 }
97
98 /// <summary>
99 /// 設置定義8個小矩形的范圍
100 /// </summary>
101 void SetRectangles()
102 {
103 //左上
104 smallRects[0] = new Rectangle(new Point(0, 0), square);
105 //右上
106 smallRects[1] = new Rectangle(new Point(this.Width - square.Width - 1, 0), square);
107 //左下
108 smallRects[2] = new Rectangle(new Point(0, this.Height - square.Height - 1), square);
109 //右下
110 smallRects[3] = new Rectangle(new Point(this.Width - square.Width - 1, this.Height - square.Height - 1), square);
111 //上中
112 smallRects[4] = new Rectangle(new Point(this.Width / 2 - 1, 0), square);
113 //下中
114 smallRects[5] = new Rectangle(new Point(this.Width / 2 - 1, this.Height - square.Height - 1), square);
115 //左中
116 smallRects[6] = new Rectangle(new Point(0, this.Height / 2 - 1), square);
117 //右中
118 smallRects[7] = new Rectangle(new Point(square.Width + baseControl.Width + 1, this.Height / 2 - 1), square);
119
120 //四條邊線
121 //左上
122 linePoints[0] = new Point(square.Width / 2, square.Height / 2);
123 //右上
124 linePoints[1] = new Point(this.Width - square.Width / 2 - 1, square.Height / 2);
125 //右下
126 linePoints[2] = new Point(this.Width - square.Width / 2 - 1, this.Height - square.Height / 2);
127 //左下
128 linePoints[3] = new Point(square.Width / 2, this.Height - square.Height / 2 - 1);
129 //左上
130 linePoints[4] = new Point(square.Width / 2, square.Height / 2);
131
132 //整個包括周圍邊框的范圍
133 ControlRect = new Rectangle(new Point(0, 0), this.Bounds.Size);
134 }
135
136 /// <summary>
137 /// 設置邊框控件可視區域
138 /// </summary>
139 /// <returns></returns>
140 private GraphicsPath BuildFrame()
141 {
142 GraphicsPath path = new GraphicsPath();
143 //上邊框
144 sideRects[0] = new Rectangle(0, 0, this.Width - square.Width - 1, square.Height + 1);
145 //左邊框
146 sideRects[1] = new Rectangle(0, square.Height + 1, square.Width + 1, this.Height - square.Height - 1);
147 //下邊框
148 sideRects[2] = new Rectangle(square.Width + 1, this.Height - square.Height - 1, this.Width - square.Width - 1, square.Height + 1);
149 //右邊框
150 sideRects[3] = new Rectangle(this.Width - square.Width - 1, 0, square.Width + 1, this.Height - square.Height - 1);
151
152 path.AddRectangle(sideRects[0]);
153 path.AddRectangle(sideRects[1]);
154 path.AddRectangle(sideRects[2]);
155 path.AddRectangle(sideRects[3]);
156 return path;
157 }
158 #endregion
159
160 /// <summary>
161 /// 繪圖
162 /// </summary>
163 public void Draw()
164 {
165 this.BringToFront();
166 //g.FillRectangles(Brushes.LightGray, sideRects); //填充四條邊框的內部
167 Pen pen = new Pen(Color.Black);
168 pen.DashStyle = DashStyle.Dot;//設置為虛線,用虛線畫四邊,模擬微軟效果
169 g.DrawLines(pen, linePoints);//繪制四條邊線
170 g.FillRectangles(Brushes.White, smallRects); //填充8個小矩形的內部
171 foreach (Rectangle smallRect in smallRects)
172 {
173 g.DrawEllipse(Pens.Black, smallRect); //繪制8個小橢圓
174 }
175 //g.DrawRectangles(Pens.Black, smallRects); //繪制8個小矩形的黑色邊線
176 }
177
178 /// <summary>
179 /// 設置光標狀態
180 /// </summary>
181 public bool SetCursorShape(int x, int y)
182 {
183 Point point = new Point(x, y);
184 if (!ControlRect.Contains(point))
185 {
186 Cursor.Current = Cursors.Arrow;
187 return false;
188 }
189 else if (smallRects[0].Contains(point))
190 {
191 Cursor.Current = Cursors.SizeNWSE;
192 mpoc = MousePosOnCtrl.TOPLEFT;
193 }
194 else if (smallRects[1].Contains(point))
195 {
196 Cursor.Current = Cursors.SizeNESW;
197 mpoc = MousePosOnCtrl.TOPRIGHT;
198 }
199 else if (smallRects[2].Contains(point))
200 {
201 Cursor.Current = Cursors.SizeNESW;
202 mpoc = MousePosOnCtrl.BOTTOMLEFT;
203 }
204 else if (smallRects[3].Contains(point))
205 {
206 Cursor.Current = Cursors.SizeNWSE;
207 mpoc = MousePosOnCtrl.BOTTOMRIGHT;
208 }
209 else if (sideRects[0].Contains(point))
210 {
211 Cursor.Current = Cursors.SizeNS;
212 mpoc = MousePosOnCtrl.TOP;
213 }
214 else if (sideRects[1].Contains(point))
215 {
216 Cursor.Current = Cursors.SizeWE;
217 mpoc = MousePosOnCtrl.LEFT;
218 }
219 else if (sideRects[2].Contains(point))
220 {
221 Cursor.Current = Cursors.SizeNS;
222 mpoc = MousePosOnCtrl.BOTTOM;
223 }
224 else if (sideRects[3].Contains(point))
225 {
226 Cursor.Current = Cursors.SizeWE;
227 mpoc = MousePosOnCtrl.RIGHT;
228 }
229 else
230 {
231 Cursor.Current = Cursors.Arrow;
232 }
233 return true;
234 }
235
236 /// <summary>
237 /// 控件移動
238 /// </summary>
239 private void ControlMove()
240 {
241 cPoint = Cursor.Position;
242 int x = cPoint.X - pPoint.X;
243 int y = cPoint.Y - pPoint.Y;
244 switch (this.mpoc)
245 {
246 case MousePosOnCtrl.TOP:
247 if (baseControl.Height - y > MinHeight)
248 {
249 baseControl.Top += y;
250 baseControl.Height -= y;
251 }
252 else
253 {
254 baseControl.Top -= MinHeight - baseControl.Height;
255 baseControl.Height = MinHeight;
256 }
257 break;
258 case MousePosOnCtrl.BOTTOM:
259 if (baseControl.Height + y > MinHeight)
260 {
261 baseControl.Height += y;
262 }
263 else
264 {
265 baseControl.Height = MinHeight;
266 }
267 break;
268 case MousePosOnCtrl.LEFT:
269 if (baseControl.Width - x > MinWidth)
270 {
271 baseControl.Left += x;
272 baseControl.Width -= x;
273 }
274 else
275 {
276 baseControl.Left -= MinWidth - baseControl.Width;
277 baseControl.Width = MinWidth;
278 }
279
280 break;
281 case MousePosOnCtrl.RIGHT:
282 if (baseControl.Width + x > MinWidth)
283 {
284 baseControl.Width += x;
285 }
286 else
287 {
288 baseControl.Width = MinWidth;
289 }
290 break;
291 case MousePosOnCtrl.TOPLEFT:
292 if (baseControl.Height - y > MinHeight)
293 {
294 baseControl.Top += y;
295 baseControl.Height -= y;
296 }
297 else
298 {
299 baseControl.Top -= MinHeight - baseControl.Height;
300 baseControl.Height = MinHeight;
301 }
302 if (baseControl.Width - x > MinWidth)
303 {
304 baseControl.Left += x;
305 baseControl.Width -= x;
306 }
307 else
308 {
309 baseControl.Left -= MinWidth - baseControl.Width;
310 baseControl.Width = MinWidth;
311 }
312 break;
313 case MousePosOnCtrl.TOPRIGHT:
314 if (baseControl.Height - y > MinHeight)
315 {
316 baseControl.Top += y;
317 baseControl.Height -= y;
318 }
319 else
320 {
321 baseControl.Top -= MinHeight - baseControl.Height;
322 baseControl.Height = MinHeight;
323 }
324 if (baseControl.Width + x > MinWidth)
325 {
326 baseControl.Width += x;
327 }
328 else
329 {
330 baseControl.Width = MinWidth;
331 }
332 break;
333 case MousePosOnCtrl.BOTTOMLEFT:
334 if (baseControl.Height + y > MinHeight)
335 {
336 baseControl.Height += y;
337 }
338 else
339 {
340 baseControl.Height = MinHeight;
341 }
342 if (baseControl.Width - x > MinWidth)
343 {
344 baseControl.Left += x;
345 baseControl.Width -= x;
346 }
347 else
348 {
349 baseControl.Left -= MinWidth - baseControl.Width;
350 baseControl.Width = MinWidth;
351 }
352 break;
353 case MousePosOnCtrl.BOTTOMRIGHT:
354 if (baseControl.Height + y > MinHeight)
355 {
356 baseControl.Height += y;
357 }
358 else
359 {
360 baseControl.Height = MinHeight;
361 }
362 if (baseControl.Width + x > MinWidth)
363 {
364 baseControl.Width += x;
365 }
366 else
367 {
368 baseControl.Width = MinWidth;
369 }
370 break;
371
372 }
373 pPoint = Cursor.Position;
374 }
375
376 #endregion
377
378 #region Events
379 /// <summary>
380 /// 鼠標按下事件:記錄當前鼠標相對窗體的坐標
381 /// </summary>
382 void FrameControl_MouseDown(object sender, MouseEventArgs e)
383 {
384 pPoint = Cursor.Position;
385 }
386
387 /// <summary>
388 /// 鼠標移動事件:讓控件跟著鼠標移動
389 /// </summary>
390 void FrameControl_MouseMove(object sender, MouseEventArgs e)
391 {
392 if (e.Button == MouseButtons.Left)
393 {
394 this.Visible = false;
395 MoveControl.DrawDragBound(baseControl);
396 ControlMove();
397 }
398 else
399 {
400 this.Visible = true;
401 SetCursorShape(e.X, e.Y); //更新鼠標指針樣式
402 }
403 }
404
405 /// <summary>
406 /// 鼠標彈起事件:讓自定義的邊框出現
407 /// </summary>
408 void FrameControl_MouseUp(object sender, MouseEventArgs e)
409 {
410 this.baseControl.Refresh(); //刷掉黑色邊框
411 this.Visible = true;
412 CreateBounds();
413 Draw();
414 }
415 #endregion
416 }
417 }
四、遺留問題
1.ListBox存在拖拉高度時,存在莫名奇妙的BUG。
2.目前該版本只支持單控件的拖拉,多控件同時拖拉等下次有空再弄。
五、附源代碼下載:http://www.BkJia.com/uploadfile/2012/0516/20120516090659425.zip
摘自 SamWang