用C#實現不規則窗體

iteye_20683發表於2010-01-08


作者:光腳丫思考 524130780@QQ.COM
文件建立時間:1/1/2010 9:52:59 PM

如何實現不規則窗體?
TransparencyKey:獲取或設定將表示窗體透明區域的顏色。
FormBorderStyle:獲取或設定窗體的邊框樣式。
BackgroundImage:獲取或設定在控制元件中顯示的背景影像。

首先,使用影像處理軟體製作出所要實現的窗體樣式,最後實現的窗體樣式就和繪製的圖片一樣。然後,將窗體的BackgroundImage屬性設定為所繪製的圖片。根據圖片的大小設定窗體的大小,即窗體的寬度等於圖片的寬度,窗體的高度等於圖片的高度。之所以這樣做,是為了避免背景圖片在窗體上的重複顯示。
接著,將窗體的FormBorderStyle設定為None,也即不要顯示窗體的邊框。這樣便只顯示帶有背景的窗體內容區,此時看起來整個窗體就和所指定的背景圖片一致。但是此時實現的窗體樣式仍然是規規矩矩的四邊形。只要將圖片中的背景顏色修改為透明色,那麼整個窗體的樣式就和圖片中的繪圖區域保持一致了。要實現這點可以將窗體的TransparencyKey設定為圖片的背景顏色,這樣以來,當窗體執行時,窗體的背景圖片中包含此顏色的區域都將被透明化。(應該是這樣的,可是實現的程式碼中貌似不是這樣的,那個背景色還是存在的。)
還有一點,由於將窗體的FormBorderStyle設定為None,窗體便沒有了標題欄,因此預設情況下窗體不可移動。下面將自己實現窗體的移動效果。


如何實現窗體的移動?
Location:設定或獲取窗體在螢幕中的位置。
通過修改Location的屬性值達到修改窗體在螢幕中位置的目的。通常是通過單擊滑鼠左鍵並移動滑鼠來移動窗體的。也就是說,滑鼠在窗體上移動的情況至少有2種,其一是不單擊滑鼠左鍵的移動,此時程式碼不需要隨著滑鼠的移動來移動窗體;其二是單擊滑鼠左鍵的同時移動滑鼠,此時就需要跟隨滑鼠來移動窗體了。要實現的要過和通過窗體標題欄移動是一樣的,只是我們要讓它在窗體的任意區域都能夠移動。
可以通過Control.MousePosition屬性獲取滑鼠單擊左鍵時的座標,此座標屬於螢幕座標系統。同樣的,窗體的Location也是螢幕座標系統,這和窗體上的控制元件的Location是不一樣的,控制元件的Location是窗體範圍內的座標系統,即,座標X值和座標Y值是相對於窗體左上角X=0,Y=0的位置而確定的。而Control.MousePosition和窗體的Location則是相對於螢幕左上角的位置而言的。
知道了滑鼠左鍵單擊時所處的螢幕座標點,也知道窗體左上角在滑鼠左鍵單擊時的螢幕座標點,通過這2個座標點就可以計算出窗體左上角相對於滑鼠單擊時的螢幕座標點的偏移量。然後,隨著滑鼠的不斷移動,程式碼隨時獲取滑鼠移動後所處的螢幕座標點,將這個新的座標點和前面計算出的偏移量再次進行計算,就可以獲取螢幕隨著滑鼠移動後應處的位置,再把這個值賦給窗體的Location屬性,窗體不就隨著滑鼠而移動了嗎!!!^_^

程式碼如下:

首先定義兩個似有變數,一個用來儲存滑鼠單擊點和窗體左上角的偏移量,一個用來標記滑鼠左鍵是否正處於按下狀態。

/// <summary> /// 用來記錄滑鼠的偏移量。 /// </summary> Point MouseOffset = new Point(); /// <summary> /// 用來標記滑鼠左鍵是否已經按下,如果按下則為true;否則為false。 /// </summary> bool IsMouseLeftButtonDown = false;


當滑鼠在窗體上單擊左鍵時,獲取滑鼠此時的螢幕座標值,並與窗體的Location進行計算,得出偏移量。

private void MainForm_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { this.IsMouseLeftButtonDown = true; Point MousePosition = Control.MousePosition; int XOffset = MousePosition.X - this.Location.X; int YOffset = MousePosition.Y - this.Location.Y; this.MouseOffset = new Point(XOffset, YOffset); } }


接著就該開始移動滑鼠了,在移動滑鼠時確定按下滑鼠左鍵,然後獲取滑鼠移動後的座標值,與前面計算的偏移量進行計算,得出窗體左上角的螢幕座標值,並將其賦給窗體的Location。

private void MainForm_MouseMove(object sender, MouseEventArgs e) { if (this.IsMouseLeftButtonDown) { Point MousePosition = Control.MousePosition; MousePosition.Offset(-this.MouseOffset.X, -this.MouseOffset.Y); this.Location = MousePosition; } }

程式碼中為什麼偏移量的X、Y值都取負值呢?這是由窗體左上角位置和滑鼠單擊時位置的對應關係確定的。既然是在窗體上單擊滑鼠,那麼其單擊點的X和Y值就必定要比窗體左上角的X和Y值大,取負值實際上等於是減去偏移量的值。

當滑鼠左鍵鬆開時,就該停止移動窗體了。
private void MainForm_MouseUp(object sender, MouseEventArgs e) { this.IsMouseLeftButtonDown = false; }

把IsMouseLeftButtonDown設定為false之後,滑鼠的MouseMove事件還是會繼續觸發的,只是將不會在執行移動窗體的那段程式碼,因為If條件已經不成立了。

搜尋了一下前面的那個點陣圖的背景色不能被去掉的問題,有說法是這樣的:在24位色以下的環境中可以顯示正常,但在24位色以上時黃色背景不能消失。為了確認這種說法的正確性,我將【螢幕的顏色質量】設定16位,還真就給正確顯示了。不過16位的顏色質量確實是不及32位的。總不能為了執行這個不規則的窗體程式,每次都來修改螢幕顏色質量吧?那也太過分了一點!當然可以自己編寫程式碼來解決這個問題,但此文到此為止。^_^

完整程式碼如下:

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace IrregularWindows { public partial class MainForm : Form { /// <summary> /// 用來記錄滑鼠的偏移量。 /// </summary> Point MouseOffset = new Point(); /// <summary> /// 用來標記滑鼠左鍵是否已經按下,如果按下則為true;否則為false。 /// </summary> bool IsMouseLeftButtonDown = false; public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { } /// <summary> /// 關閉應用程式。 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ExitButton_Click(object sender, EventArgs e) { this.Close(); } private void MainForm_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { this.IsMouseLeftButtonDown = true; Point MousePosition = Control.MousePosition; int XOffset = MousePosition.X - this.Location.X; int YOffset = MousePosition.Y - this.Location.Y; this.MouseOffset = new Point(XOffset, YOffset); } } private void MainForm_MouseMove(object sender, MouseEventArgs e) { if (this.IsMouseLeftButtonDown) { Point MousePosition = Control.MousePosition; MousePosition.Offset(-this.MouseOffset.X, -this.MouseOffset.Y); this.Location = MousePosition; } } private void MainForm_MouseUp(object sender, MouseEventArgs e) { this.IsMouseLeftButtonDown = false; } } }

相關文章