天天看點

用C#實作不規則窗體

作者:光腳丫思考 [email protected]

文檔建立時間:1/1/2010 9:52:59 PM

如何實作不規則窗體?

TransparencyKey:擷取或設定将表示窗體透明區域的顔色。

FormBorderStyle:擷取或設定窗體的邊框樣式。

BackgroundImage:擷取或設定在控件中顯示的背景圖像。

首先,使用圖像處理軟體制作出所要實作的窗體樣式,最後實作的窗體樣式就和繪制的圖檔一樣。然後,将窗體的BackgroundImage屬性設定為所繪制的圖檔。根據圖檔的大小設定窗體的大小,即窗體的寬度等于圖檔的寬度,窗體的高度等于圖檔的高度。之是以這樣做,是為了避免背景圖檔在窗體上的重複顯示。

接着,将窗體的FormBorderStyle設定為None,也即不要顯示窗體的邊框。這樣便隻顯示帶有背景的窗體内容區,此時看起來整個窗體就和所指定的背景圖檔一緻。但是此時實作的窗體樣式仍然是規規矩矩的四邊形。隻要将圖檔中的背景顔色修改為透明色,那麼整個窗體的樣式就和圖檔中的繪圖區域保持一緻了。要實作這點可以将窗體的TransparencyKey設定為圖檔的背景顔色,這樣以來,當窗體運作時,窗體的背景圖檔中包含此顔色的區域都将被透明化。(應該是這樣的,可是實作的代碼中貌似不是這樣的,那個背景色還是存在的。)

還有一點,由于将窗體的FormBorderStyle設定為None,窗體便沒有了标題欄,是以預設情況下窗體不可移動。下面将自己實作窗體的移動效果。

用C#實作不規則窗體

如何實作窗體的移動?

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;

}

}

}

繼續閱讀