天天看點

java實作不規則窗體_C#建立不規則窗體的4種方式詳解

現在,C#建立不規則窗體不是一件難事,下面總結一下:

一、自定義窗體

一般為規則的圖形,如圓、橢圓等。

做法:重寫Form1_Paint事件(Form1是窗體的名字),最簡單的一種情況如下:

System.Drawing.Drawing2D.GraphicsPath shape = new System.Drawing.Drawing2D.GraphicsPath();

shape.AddEllipse(0,0,this.Height, this.Width);

this.Region = new Region(shape);

即重繪窗體的規則。

二、利用背景圖檔實作

1. 設定窗體的背景圖檔,其中背景圖檔是24位(不包括24)以下的位圖(BMP圖檔),并且要設定TansparencyKey的值,一般為你背景圖檔的背景色,即建立不規則圖檔時的底色,一般設為你圖檔中沒有的顔色。

這種做法的不好的地方就是背景圖檔一定要16位或者更低的,而且還要確定用戶端的顯示。如果螢幕的顔色深度設定大于 24 位,則不管 TransparencyKey 屬性是如何設定的,窗體的非透明部分都會産生顯示問題。若要避免出現這種問題,請確定“顯示”控制台中的螢幕顔色深度的設定小于 24 位。當開發具有這種透明功能的應用程式時,請牢記應使您的使用者意識到此問題。

實作步驟如下:

1. 建立windows application

2. 選擇窗體,找到BackgroundImage屬性,點選打開新的視窗,選擇下面的導入資源檔案,選擇你的不規則的BMP圖檔

3. 找到窗體的TansparencyKey,将它設定為你背景圖檔的背景色(如黃色)

4. 找到窗體的FormBorderStyle,将其設定為none,即不顯示标題欄

5. 運作

2. 跟背景圖檔一樣的圖形,不過是動态加載,周遊位圖以實作不規則窗體。它的原理是這樣的,在Form的load事件中寫方法使得窗體的描繪區域發生改變。

實作步驟如下:

1. 建立winform應用程式

2. 找到窗體的Load事件,輕按兩下進行編輯

3. 編寫方法,主要的代碼如下:

class BitmapRegion

{

public BitmapRegion()

{ }

///

/// Create and apply the region on the supplied control

/// 建立支援位圖區域的控件(目前有button和form)

///

/// The Control object to apply the region to控件

/// The Bitmap object to create the region from位圖

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

//将位圖設定成窗體背景圖檔

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);

}

}

///

/// Calculate the graphics path that representing the figure in the bitmap

/// excluding the transparent color which is the top left pixel.

/// //計算位圖中不透明部分的邊界

///

/// The Bitmap object to calculate our graphics path from

/// Calculated graphics path

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;

}

}

4.運作

三、調用類庫實作

主要就是根據一些坐标,然後根據這些坐标繪制窗體

代碼如下:

public Form3()

{

InitializeComponent();

//建立不規則窗體

POINTAPI[] poin;

poin = new POINTAPI[5];

poin[0].x = 90;

poin[0].y = 90;

poin[1].x = this.Width;

poin[1].y = 0;

poin[2].x = Width;

poin[2].y = this.Height / 2;

poin[3].x = Width / 2;

poin[3].y = Height / 2;

poin[4].x = 0;

poin[4].y = Width;

Boolean flag = true;

IntPtr hRgn = CreatePolygonRgn(ref poin[0], 8, 1);

SetWindowRgn(this.Handle, hRgn, ref flag);

this.BackColor = Color.BurlyWood;

}

[StructLayout(LayoutKind.Sequential)]

private struct POINTAPI

{

internal int x;

internal int y;

}

[DllImport("gdi32.dll")]

private static extern IntPtr CreatePolygonRgn(ref POINTAPI lpPoint,int nCount,int nPolyFillMode);

[DllImport("user32.dll")]

private static extern IntPtr SetWindowRgn(IntPtr hWnd,IntPtr hRgn, ref Boolean bRedraw);

//設定窗體顯示狀态

[DllImport("user32.dll")]

private static extern int SetWindowPos(IntPtr hwnd,int hWndInsertAfter,int x,int y,int cx,int cy,int wFlags);

private void Start_Btn_Click(object sender, EventArgs e)

{//始終顯示在前面

SetWindowPos(this.Handle, -1, 0, 0, 0, 0, 1);

}

private void button1_Click(object sender, EventArgs e)

{

//最小化始終顯示在前面

SetWindowPos(this.Handle, -1, 0, 0, 0, 0, 0);

}

當然,我們也可以自定義窗體的動作,如按着某個軌迹一定,下面的代碼中的BackgroundForm程式中就小試了一下,效果還不錯,下面是這些程式的效果圖:

java實作不規則窗體_C#建立不規則窗體的4種方式詳解

代碼是.Net 2.0的,也可以轉換為其他版本的,隻要運作主程式即可。

以上的四種方法有利也有弊,希望大家提意見或者更好的解決方案。