本文轉自翔宇網http://www.biye5u.com/article/Csharp/winform/2010/2593.html
以前想製作不規則表單,大多使用API函數來實現,在C#中,也可以不使用API函數照樣能製作出漂亮的不規則表單,下面就介紹一下相關方法。
1、首先準備一張BMP格式的圖片
圖片的形式隨意,但注意圖片的背景最好設定成C#中提供的一些色系,如白色(#FFFFFF\white)、黑色(#000000\black)、黃色(#FFFF00\yellow)、藍色(#0000FF\blue)、紅色(#FF0000\red)或綠色(#00FF00\green)等。本文使用如下形式的圖片,其背景為白色。
2、建立Windows程式
開啟Visual studio 2005,當然,這裡使用的是VS2005,具體是什麼版本無所謂關鍵是方法。建立一個windows應用程式,項目起名為abnormalwin,如所示:
設定完成後單擊【確定】,系統自動建立好一個預設的介面,並自動命名為form1。
3、設定相關屬性
(1)將 FormBorderStyle 屬性設定為 None;
(2)將表單的 BackgroundImage 屬性設定為前面準備好的BMP圖片;
(3)將 TransparencyKey 屬性設定為位元影像檔案的背景色,本例中為白色。
如果你的電腦顏色設定低於24位,現在就可以產生相應的效果了,但是如果你的電腦顏色高於24位,就不會產生任何效果,這怎麼辦呢?有人想辦法用以下方式解決了這個問題。
4、定義一個圖片處理類BitmapRegion
這個類是有熱心網友翻譯國外的文章而來的。具體定義方法如下:
(1)在解決方案項目abnormalwin上右擊後,選擇【添加】—>【類】,如所示操作:
(2)在彈出的添加新項表單中,輸入類的名稱BitmapRegion.cs,然後單擊【添加】。
(3)輸入下面的代碼
將類檔案中自動產生的程式碼用如下代碼代替之:
View Code
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Text;
namespace abnormalwin
{
public class BitmapRegion
{
public BitmapRegion()
{ }
///<summary>
///Create and apply the region on the supplied control
///建立支援位元影像地區的控制項(目前有button和form)
///</summary>
///<param name="control">The Control object to apply the region to控制項</param>
///<param name="bitmap">The Bitmap object to create the region from位元影像</param>
public static void CreateControlRegion(Control control, Bitmap bitmap)
{
// Return if control and bitmap are null
//判斷是否存在控制項和位元影像
if (control == null || bitmap == null)
return;
// Set our control''s size to be the same as the bitmap
//設定控制項大小為位元影像大小
control.Width = bitmap.Width;
control.Height = bitmap.Height;
// Check if we are dealing with Form here
//當控制項是form時
if (control is System.Windows.Forms.Form)
{
// Cast to a Form object
//強制轉換為FORM
Form form = (Form)control;
// Set our form''s size to be a little larger that the bitmap just
// in case the form''s border style is not set to none in the first place
//當FORM的邊界FormBorderStyle不為NONE時,應將FORM的大小設定成比位元影像大小稍大一點
form.Width = control.Width;
form.Height = control.Height;
// No border
//沒有邊界
form.FormBorderStyle = FormBorderStyle.None;
// Set bitmap as the background image
//將位元影像設定成表單背景圖片 http://www.mscto.com
form.BackgroundImage = bitmap;
// Calculate the graphics path based on the bitmap supplied
//計算位元影像中不透明部分的邊界
GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
// Apply new region
//應用新的地區
form.Region = new Region(graphicsPath);
}
// Check if we are dealing with Button here
//當控制項是button時
else if (control is System.Windows.Forms.Button)
{
// Cast to a button object
//強制轉換為 button
Button button = (Button)control;
// Do not show button text
//不顯示button text
button.Text = "";
// Change cursor to hand when over button
//改變 cursor的style
button.Cursor = Cursors.Hand;
// Set background image of button
//設定button的背景圖片
button.BackgroundImage = bitmap;
// Calculate the graphics path based on the bitmap supplied
//計算位元影像中不透明部分的邊界
GraphicsPath graphicsPath = CalculateControlGraphicsPath(bitmap);
// Apply new region
//應用新的地區
button.Region = new Region(graphicsPath);
}
}
///<summary>
/// Calculate the graphics path that representing the figure in the bitmap
/// excluding the transparent color which is the top left pixel.
/// 計算位元影像中不透明部分的邊界
///</summary>
///<param name="bitmap">The Bitmap object to calculate our graphics path from</param>
///<returns>Calculated graphics path</returns>
private static GraphicsPath CalculateControlGraphicsPath(Bitmap bitmap)
{
// Create GraphicsPath for our bitmap calculation
//建立 GraphicsPath
GraphicsPath graphicsPath = new GraphicsPath();
// Use the top left pixel as our transparent color
//使用左上方的一點的顏色作為我們透明色
Color colorTransparent = bitmap.GetPixel(0, 0);
// This is to store the column value where an opaque pixel is first found.
// This value will determine where we start scanning for trailing opaque pixels.
//第一個找到點的X
int colOpaquePixel = 0;
// Go through all rows (Y axis)
// 偏曆所有行(Y方向)
for (int row = 0; row < bitmap.Height; row++)
{
// Reset value
//重設
colOpaquePixel = 0;
// Go through all columns (X axis)
//偏曆所有列(X方向)
for (int col = 0; col < bitmap.Width; col++)
{
// If this is an opaque pixel, mark it and search for anymore trailing behind
//如果是不需要透明處理的點則標記,然後繼續偏曆
if (bitmap.GetPixel(col, row) != colorTransparent)
{
// Opaque pixel found, mark current position
//記錄當前
colOpaquePixel = col;
// Create another variable to set the current pixel position
//建立新變數來記錄當前點
int colNext = col;
// Starting from current found opaque pixel, search for anymore opaque pixels
// trailing behind, until a transparent pixel is found or minimum width is reached
//從找到的不透明點開始,繼續尋找不透明點,一直到找到或則達到圖片寬度
for (colNext = colOpaquePixel; colNext < bitmap.Width; colNext++)
if (bitmap.GetPixel(colNext, row) == colorTransparent)
break;
// Form a rectangle for line of opaque pixels found and add it to our graphics path
//將不透明點加到graphics path
graphicsPath.AddRectangle(new Rectangle(colOpaquePixel, row, colNext - colOpaquePixel, 1));
// No need to scan the line of opaque pixels just found
col = colNext;
}
}
}
// Return calculated graphics path
return graphicsPath;
}
}
}
5、為表單的Load事件編寫程式
雙擊表單,程式預設是為表單的Load事件添加處理常式,然後在游標處書寫下面的代碼:
BitmapRegion BitmapRegion = new BitmapRegion();//此為產生不規則表單和控制項的類BitmapRegion.CreateControlRegion(this, new Bitmap("xyt.bmp"));
6、使表單能夠最大化、最小化和關閉
在程式相應位置添加三個按鈕控制項,主要是為了實現最大化、最小化和關閉功能,並且將三個按鈕的文本分別設定為“口,—,X”,或者自己使用比較漂亮的圖片按鈕會更好,如果你借用按鈕的滑鼠滑過、按下、放下等事件實現更進階的效果那會更炫。
(1)雙擊最大化按鈕,程式自動添加按鈕的單擊事件處理常式,編寫代碼如下:
if (this.WindowState == FormWindowState.Maximized)//如果已經最大化 this.WindowState = FormWindowState.Normal;//視窗正常大小 else this.WindowState = FormWindowState.Maximized; //視窗最大化
(2)用同樣的方法為最小化按鈕添加如下程式碼:
this.WindowState = FormWindowState.Minimized;//視窗最小化
(3)用同樣的方法為關閉按鈕添加如下程式碼:
this.Close();
7、實現表單的拖拽功能
首先為該表單添加兩個成員變數:雙擊表單介面,找到如下代碼:
public Form1() { InitializeComponent(); }
在該代碼前添加如下兩個變數成員:
private Point mouseOffset; //記錄滑鼠指標的座標
private bool isMouseDown = false; //記錄滑鼠按鍵是否按下
回到設計介面,在右側屬性視窗中找到事件表徵圖(類似閃電的表徵圖),單擊該按鈕,轉換到表單的事件介面,接下來為其添加相關事件處理常式。
(1)找到MouseDown事件,雙擊該事件,在游標處添加如下代碼:
private void Form1_MouseDown(object sender, MouseEventArgs e) { int xOffset; int yOffset; if (e.Button == MouseButtons.Left) { xOffset = -e.X - SystemInformation.FrameBorderSize.Width; yOffset = -e.Y - SystemInformation.CaptionHeight - SystemInformation.FrameBorderSize.Height; mouseOffset = new Point(xOffset, yOffset); isMouseDown = true; } }
(2)找到MouseMove事件,雙擊該事件後,為其添加如下代碼:
private void Form1_MouseMove(object sender, MouseEventArgs e) { if (isMouseDown) { Point mousePos = Control.MousePosition; mousePos.Offset(mouseOffset.X, mouseOffset.Y); Location = mousePos; } }
(3)找到MouseUp事件,雙擊該事件後為其添加如下代碼:
private void Form1_MouseUp(object sender, MouseEventArgs e) { // 修改滑鼠狀態isMouseDown的值 // 確保只有滑鼠左鍵按下並移動時,才移動表單 if (e.Button == MouseButtons.Left) { isMouseDown = false; } }
8、程式運行效果
按下F5鍵就可以看一下程式的運行效果了,本例的運行效果如下所示:
9、本方法的優劣勢
使用此方法製作的不規則表單,相對API來說編寫的代碼較少,對於複雜的不規則表單來說較好,但是執行效率較低,應為程式運行起來後,他調用BitmapRegion類的相關方法把你設定的底色一點點的去掉,因此速度相對較慢,如果機器運行較慢的話,會看到這個過程。
本例原始碼下載:點擊下載此檔案