一起谈.NET技术,C#创建不规则窗体的几种方式
????現(xiàn)在,C#創(chuàng)建不規(guī)則窗體不是一件難事,下面總結(jié)一下:
????? 一、自定義窗體,一般為規(guī)則的圖形,如圓、橢圓等。
做法:重寫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);
即重繪窗體的規(guī)則。
??? 二、利用背景圖片實(shí)現(xiàn)
????? 1.?????? 設(shè)置窗體的背景圖片,其中背景圖片是24位(不包括24)以下的位圖(BMP圖片),并且要設(shè)置TansparencyKey的值,一般為你背景圖片的背景色,即創(chuàng)建不規(guī)則圖片時的底色,一般設(shè)為你圖片中沒有的顏色。
??? 這種做法的不好的地方就是背景圖片一定要16位或者更低的,而且還要確保客戶端的顯示。如果監(jiān)視器的顏色深度設(shè)置大于 24 位,則不管 TransparencyKey 屬性是如何設(shè)置的,窗體的非透明部分都會產(chǎn)生顯示問題。若要避免出現(xiàn)這種問題,請確?!帮@示”控制面板中的監(jiān)視器顏色深度的設(shè)置小于 24 位。當(dāng)開發(fā)具有這種透明功能的應(yīng)用程序時,請牢記應(yīng)使您的用戶意識到此問題。
???? 實(shí)現(xiàn)步驟如下:
1.?新建windows application
2.?選擇窗體,找到BackgroundImage屬性,點(diǎn)擊打開新的窗口,選擇下面的導(dǎo)入資源文件,選擇你的不規(guī)則的BMP圖片
3.?找到窗體的TansparencyKey,將它設(shè)置為你背景圖片的背景色(如黃色)
4.?找到窗體的FormBorderStyle,將其設(shè)置為none,即不顯示標(biāo)題欄
5.?運(yùn)行
????? 2.?????? 跟背景圖片一樣的圖形,不過是動態(tài)加載,遍歷位圖以實(shí)現(xiàn)不規(guī)則窗體。它的原理是這樣的,在Form的load事件中寫方法使得窗體的描繪區(qū)域發(fā)生改變。
??? 實(shí)現(xiàn)步驟如下:
1.?建立winform應(yīng)用程序
2.?找到窗體的Load事件,雙擊進(jìn)行編輯
3.?編寫方法,主要的代碼如下:
?
代碼????class?BitmapRegion
????{
????????public?BitmapRegion()
????????{?}
????????///?<summary>?
????????///?Create?and?apply?the?region?on?the?supplied?control
????????///?創(chuàng)建支持位圖區(qū)域的控件(目前有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
????????????//設(shè)置控件大小為位圖大小
????????????control.Width?=?bitmap.Width;
????????????control.Height?=?bitmap.Height;
????????????//?Check?if?we?are?dealing?with?Form?here?
????????????//當(dāng)控件是form時
????????????if?(control?is?System.Windows.Forms.Form)
????????????{
????????????????//?Cast?to?a?Form?object
????????????????//強(qiáng)制轉(zhuǎn)換為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?
????????????????//當(dāng)FORM的邊界FormBorderStyle不為NONE時,應(yīng)將FORM的大小設(shè)置成比位圖大小稍大一點(diǎn)
????????????????form.Width?=?control.Width;
????????????????form.Height?=?control.Height;
????????????????//?No?border?
????????????????//沒有邊界
????????????????form.FormBorderStyle?=?FormBorderStyle.None;
????????????????//?Set?bitmap?as?the?background?image?
????????????????//將位圖設(shè)置成窗體背景圖片
????????????????form.BackgroundImage?=?bitmap;
????????????????//?Calculate?the?graphics?path?based?on?the?bitmap?supplied?
????????????????//計算位圖中不透明部分的邊界
????????????????GraphicsPath?graphicsPath?=?CalculateControlGraphicsPath(bitmap);
????????????????//?Apply?new?region?
????????????????//應(yīng)用新的區(qū)域
????????????????form.Region?=?new?Region(graphicsPath);
????????????}
????????????//?Check?if?we?are?dealing?with?Button?here?
????????????//當(dāng)控件是button時
????????????else?if?(control?is?System.Windows.Forms.Button)
????????????{
????????????????//?Cast?to?a?button?object?
????????????????//強(qiáng)制轉(zhuǎn)換為?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?
????????????????//設(shè)置button的背景圖片
????????????????button.BackgroundImage?=?bitmap;
????????????????//?Calculate?the?graphics?path?based?on?the?bitmap?supplied?
????????????????//計算位圖中不透明部分的邊界
????????????????GraphicsPath?graphicsPath?=?CalculateControlGraphicsPath(bitmap);
????????????????//?Apply?new?region?
????????????????//應(yīng)用新的區(qū)域
????????????????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?
????????????//創(chuàng)建?GraphicsPath
????????????GraphicsPath?graphicsPath?=?new?GraphicsPath();
????????????//?Use?the?top?left?pixel?as?our?transparent?color?
????????????//使用左上角的一點(diǎn)的顏色作為我們透明色
????????????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.
????????????//第一個找到點(diǎn)的X
????????????int?colOpaquePixel?=?0;
????????????//?Go?through?all?rows?(Y?axis)?
????????????//?偏歷所有行(Y方向)
????????????for?(int?row?=?0;?row?<?bitmap.Height;?row++)
????????????{
????????????????//?Reset?value?
????????????????//重設(shè)
????????????????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?
????????????????????//如果是不需要透明處理的點(diǎn)則標(biāo)記,然后繼續(xù)偏歷
????????????????????if?(bitmap.GetPixel(col,?row)?!=?colorTransparent)
????????????????????{
????????????????????????//?Opaque?pixel?found,?mark?current?position
????????????????????????//記錄當(dāng)前
????????????????????????colOpaquePixel?=?col;
????????????????????????//?Create?another?variable?to?set?the?current?pixel?position?
????????????????????????//建立新變量來記錄當(dāng)前點(diǎn)
????????????????????????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?
????????????????????????///從找到的不透明點(diǎn)開始,繼續(xù)尋找不透明點(diǎn),一直到找到或則達(dá)到圖片寬度?
????????????????????????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?
????????????????????????//將不透明點(diǎn)加到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.?運(yùn)行
?????? 三、調(diào)用類庫實(shí)現(xiàn)
主要就是根據(jù)一些坐標(biāo),然后根據(jù)這些坐標(biāo)繪制窗體
代碼如下:
?
代碼 public?Form3()????????{
????????????InitializeComponent();
????????????//創(chuàng)建不規(guī)則窗體
????????????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);
?
????????//設(shè)置窗體顯示狀態(tài)
????????[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);
?
????????}
????? 當(dāng)然,我們也可以自定義窗體的動作,如按著某個軌跡一定,下面的代碼中的BackgroundForm程序中就小試了一下,效果還不錯,下面是這些程序的效果圖(有點(diǎn)亂)和代碼:
?
?
????? 代碼下載: 不規(guī)則窗體
????? 代碼是.Net 2.0的,也可以轉(zhuǎn)換為其他版本的,只要運(yùn)行主程序即可。(PS:圖片做的不是很好看,就隨便亂P了一通)
????? 以上的四種方法有利也有弊,希望大家提意見或者更好的解決方案。
轉(zhuǎn)載于:https://www.cnblogs.com/waw/archive/2011/09/02/2163187.html
總結(jié)
以上是生活随笔為你收集整理的一起谈.NET技术,C#创建不规则窗体的几种方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一起谈.NET技术,初识Silverli
- 下一篇: asp.net treeView 节点