程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#實現拖拉控件改變位置與大小(SamWang)(附源代碼下載)

C#實現拖拉控件改變位置與大小(SamWang)(附源代碼下載)

編輯:C#入門知識

前言:

  很多時候我們需要在運行時,動態地改變控件的位置以及大小,以獲得更好的布局。比如說實際項目中的可自定義的報表、可自定義的單據等諸如此類。它們有個特點就是允許客戶或者二次開發人員設計它們需要的界面設置功能。

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

  本篇主要討論下,在運行時如何實現拖拉控件,達到改變控件位置與大小。功能將模擬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
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved