用C#建立可拖動表單
原著:lover_P
所謂“可拖動表單”就是無需拖動標題列就可以拖動的表單,這在一個沒有標題列的表單上是一種非常有用的技術。關於這一方面的技巧,網上已經有很多介紹,但都不是很詳盡,有些實現也不夠簡潔。最主要的,這些介紹大多是大片大片的原始碼,很少講解;初學者學期來恐怕要費些力氣(我在學習這個技巧的時候就很痛苦)。在這裡,我對這個技巧進行了一個詳細的講解,相信各位初學者朋友可以學會如何製作可拖動表單。
(註:本文期望的讀者是那些有一定用C#開發Windows程式基礎但暫時還不會製作可拖動表單的朋友。)
首先,我們來複習一下一個Windows表單的組成。請看這張圖:
圖1 Windows表單構成
這是一個形式化的標準Windows表單。首先,表單的頂部是一個標題列,其餘的部分是表單的主體,包圍在表單主體外圍的是一個邊框,邊框內不就是我們放置控制項或繪製圖形的使用者區。
圖中還標明了各種表單構造元素的尺寸的獲得方法。對於使用者區,System.Windows.Forms.Form提供了執行個體屬性ClientSize,相信大家已經很熟悉了。而要想活棋一般性的表單構造元素(如標題列、邊框等)的尺寸,我們可以使用.NET類庫中提供的一個類:System.Windows.Forms.SystemInformation,這個類提供了一些靜態屬性如表示標題列高度的CaptionHeight。有關SystemInformation類的資訊可以在.NET SDK文檔目錄“.NET Framework SDK -> 參考 -> 類庫 -> System.Windows.Forms -> SystemInformation 類”處找到(註:這裡的超連結只在您安裝了.NET Framework 1.1簡體中文版並且安裝了配套文檔時才有效)。這是一個很有用的類,希望大家能夠記住它(可能您早就知道了,可我是才知道的-_-汗~~)。
接下來,我們來看看如何在在使用者區拖動滑鼠時移動表單。請看下面這張圖:
圖2 表單的移動
我們來觀察滑鼠在表單內的位置和表單的移動,很容易可以發現:在表單被拖動的過程中,滑鼠在表單內的相對位置是始終不變的!那麼,我們只要檢測到滑鼠在螢幕中的移動並修改表單的位置就可以達到拖動表單的目的!
我們知道,在滑鼠訊息/事件處理中,只能得到滑鼠相對於表單的位置。那麼,如何知道滑鼠在螢幕中的位置呢?這裡又要提到一個類:System.Windows.Forms.Control類。也許你會很吃驚:這不是所有控制項的基類嗎?呵呵~是這樣di。不過,儘管是這樣,Control類卻沒有像其他廣泛使用的基類那樣被聲明為抽象類別,而且它提供了一個靜態屬性:MousePosition,通過這個屬性可以得到滑鼠相對於螢幕的位置。有關Control類的資訊可以在.NET Framework文檔目錄“.NET Framework SDK -> 參考 -> 類庫 -> System.Windows.Forms -> Control 類”處找到(註:這裡的超連結只在您安裝了.NET Framework 1.1簡體中文版並且安裝了配套文檔時才有效)。
知道了如何擷取這些資訊之後,製作移動表單實際上就成了一個很簡單的問題了。基本過程是這樣的:首先,在滑鼠(左鍵或一個你喜歡的鍵)按下時,記錄滑鼠位置;由於在移動的過程中,滑鼠的螢幕座標發生變化但表單相對座標不變,我們可以推算出表單位置的變化為(假設mousePosition具有System.Drawing.Point類型,表示滑鼠在表單中的相對座標):
// 範例程式碼1
Form.Top = Control.MousePosition.Y - mousePosition.Y;
Form.Left = Control.MousePosition.X - mousePosition.X;
這樣還不行,因為我們的mousePosition表示的是滑鼠在表單使用者區內的相對座標,但在移動表單的時候還要考慮表單標題列和邊框的尺寸。在上面的基礎上,我們將代碼修正為:
// 範例程式碼2
Form.Top = Control.MousePosition.Y - mousePosition.Y
- SystemInformation.FrameBorderSize.Height - SystemInformation.CaptionHeight;
Form.Left = Control.MousePosition.Y - mousePosition.Y
- SystemInformation.FrameBorderSize.Width;
也就是說,在高度上(縱座標)要減去標題列的高度和邊框的高度,而在寬度上(橫座標)要減去邊框的寬度。然而,當製作一個既沒有標題列也沒有邊框的可拖動表單時,使用“範例程式碼1”所示的代碼就可以了。
上面的代碼只是一個示範性代碼。具體的操作如下:
首先,為表單添加一個私人域:
private System.Drawing.Point mousePoint;
然後,為表單添加滑鼠按下事件處理方法(我這裡是MainForm_MouseDown,別忘了將該方法連結到MainForm.MouseDown事件,這不用多說了吧?):
private void MainForm_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) {
if(e.Button == MouseButtons.Left) {
this.mousePosition.X = e.X;
this.mousePosition.Y = e.Y;
}
}
在這裡注意對滑鼠按鍵進行篩選。
接下來,為表單添加滑鼠移動事件處理方法(我這裡是MainForm_MouseMove):
private void MainForm_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) {
if(e.Button == MouseButtons.Left) {
Form.Top = Control.MousePosition.Y - mousePosition.Y
- SystemInformation.FrameBorderSize.Height - SystemInformation.CaptionHeight;
Form.Left = Control.MousePosition.Y - mousePosition.Y
- SystemInformation.FrameBorderSize.Width;
}
}
這裡,如果表單沒有標題列,可以去掉“-SystemInformation.CaptionHeight”;如果表單沒有邊框,還可以去掉“-SystemInformation.FrameBorderSize.Height”和“-SystemInformation.FrameBorderSize.Width”。
現在,您是不是已經很清楚地明白如何用C#製作可拖動視窗了?祝賀您!最後,送您一個小禮物——案頭時鐘。很簡潔、很有意思哦~~~
另外贈送小技巧三則:
這個技巧我掌握的還不是很豐富,現在介紹一種最簡單的方法——通過設定表單的Region屬性。首先,聲明一個System.Drawing.Drawing2D.GraphicsPath變數,在這個變數中添加您期望作為表單輪廓的形狀組合;之後,從這個變數產生一個System.Drawing.Region執行個體,並賦給表單的Region屬性即可。如:
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(0, 0, 120, 120);
Region r = new Region(gp);
this.Region = r;
將上述代碼添加到表單的建構函式中,我們就能夠得到一個自訂的表單了,這個表單是一個直徑為120像素的圓形(也是我的時鐘的外觀哦)。
將表單的FormBorderStyle設定為None即可。這很簡單事嗎?那麼
首先將表單的ControlBox屬性設定為false,也就是不要控制按鈕(表單表徵圖、最大最小化按鈕和關閉按鈕)。按說這時就不應該有標題列了,但我們還能看到它很煩人地待在那裡,因此,我們要把表單的Text屬性設定為空白(注意是String.Empty,而不是null)。