跟我學做c#皮膚美化(六)
跟我學做c#皮膚美化(六)
--MainForm窗體的制作3
在上一篇中,我們雖然已經做出界面大概的樣子出來了。不過還是存在著一些問題,包括運行緩慢和閃爍等一些問題。那么下面就讓我們一起來解決吧。
先來說說閃爍和緩慢的問題。
我認為最主要的還是由于我們設置了transparent所造成的。網上的一些解釋是這樣的,當窗體顯示時我們設置的透明部分在顯示的時候會先呈現出黑色然后再在上面顯示圖片。這樣一來控件一多我們很容易就看見了。不管解釋的對不對,反正我們知道設置窗體的transparent肯定是對窗體的顯示有一些負面影響的(接下來的窗體避免設置transparent也確實證明了這一點)。既然是這個transparent“搞的鬼”,那能不能不用它來實現窗體的透明呢?答案是我還沒找到。但是不代表這個問題解決不了。
我們不妨先來回憶一下我們為什么要使用這個transparent。還記得下面這張圖吧?

我們運用transparent就是為了解決四個角上透明度的問題。現在我們不想使用transparent怎么辦呢?其實簡單的換個思路就行了。我們為什么非要那邊是透明的啊,它不透明就讓它不透明唄,我們只要在顯示的時候“切掉”它不就行了。也就是說我們自己先要在原有的窗口內畫出一個圓矩形出來然后四個直角就自然切掉不要了。那怎么畫怎么切?看下面的系統API,


第一個是用來畫的,而第二個當然就是用來切的啦。MSDN上面已經給我們解釋的很清楚了。CreateRoundRectRgn前面四個參數分別是左上角和右下角的坐標,我們在畫的時候只需要將其起點設置為(1,1)終點設置為(this.width-1,this.height-1)就能得到一個外邊距相當于1的矩形啦。如圖:
圖中的藍色部分就是我們需要省略的部分。

最后兩個參數分別是橢圓形的寬高(其實就是我們切的圓角的弧度啦)。這個函數執行成功了就會返回切好的區域的句柄,然后我們只要在SetWindowRgn中拿到這個handle就可以把我們需要的圓矩形部分切下來啦。
可是好像又有一個問題那!到底該什么時候切呢?鉛筆,刀都準備好了,但總不能讓他傻傻站那兒不知道什么時候動手吧!時機很重要。我們應該讓他在窗體大小變化的時候就行動一次,這樣才能保證每次窗體大小變化(比如說最大化)后還能保證是圓角矩形。好啦,原理講好了,現在該真正動手干活咯。
首先第一步就是切掉原來窗體的transparent,這個就不用我多說了吧!會設置還不會取消嘛!接著就重寫一個OnResize函數就可以啦。兩句話搞定,
protected overridevoid OnResize(EventArgse)
{
base.OnResize(e);
intRgn = Win32.CreateRoundRectRgn(1, 1, this.Width - 1, this.Height- 1, 7, 7);
Win32.SetWindowRgn(this.Handle, Rgn, true);
}
好了,來運行一下看看效果吧!

現在我們再來最大化,最小化還原看看效果確實比上次好多了。基本看不到左上角還有閃爍的情況了,而且響應也蠻快的。不過大家也從上圖看出來了,就是最大化的時候周圍有空隙的啊。其實也不難想到這些空隙就是我們切掉不要的那一部分窗體。要想最大化的時候窗體完全覆蓋只要在最大化的時候稍微增加一下窗體的寬和高就是了。于是我們在上一期的代碼中再對最大化事件做以下修改。
private voidbtmax_Click(object sender, EventArgs e)
{
this.btmax.Top-= 30;
this.btres.Top= 0;
//最大化之前記錄窗口信息便于縮小
orginHeight = this.Height;
orginWidth = this.Width;
X = this.Location.X;
Y = this.Location.Y;
this.Top= 1;
this.Left= 1;
BorderWidth = Screen.PrimaryScreen.WorkingArea.Width +4;
BorderHeight = Screen.PrimaryScreen.WorkingArea.Height +4;
st = stat.Max;
}
其中這個窗體的寬和高我試了一下,加4正好差不多能覆蓋原來的空隙了。大家可以試一下。
OK,閃爍終于算是解決了。接下來實現窗體大小的拖動功能。
這個問題還是由于我們的窗體樣式為None導致的(看來這個None還真是搞出了不少麻煩呢)。不過不管怎樣,咱還是想辦法解決吧。前面的窗口移動我們是通過API來完成的,沒有疑問的大小的調整我們也借助系統API發送消息來完成。Win32.SendMessage(Handle,274, 61440 + x, 0);其中的x代表了不同的數字,當數字不同的時候產生的拖動大小的方向也不同。具體的數字代表的方向大家可以看我的代碼。
現在最主要的問題就是實現鼠標到達窗體邊緣時可以拖動。這里我運用了MouseMove這個事件。當鼠標到達指定區域時我們通過判斷鼠標左鍵是否按下來實現改變大小消息的發送與否。我舉一個稍微復雜一點的事件說一下吧。拿右上角來說吧。右上角運用ptbtr_MouseMove這個事件來判斷是否更改大小。看圖:

我將右上角的區域分為了四個區域。當鼠標分別落在1,2,4區域并按下鼠標的時候我們才相應的賦予x值從而改變窗體大小。那么如何判斷鼠標經過的區域呢?我們可以直接用MouseEventArgs e參數中的x,y屬性。該屬性表明了鼠標在相應的panel或者picture下的相對位置。還好是相對位置,不然我們又要麻煩了,呵呵。
看代碼:首先我們用if (!sizeAble)判斷是否設置了可更改大小。當可以改變大小時,我們再逐一判斷鼠標左鍵按下時鼠標的位置,并相應作出更改。代碼中我那個點是采用3個像素的位置作為分界線的(就是1和4的分界區),這個位置如果大家覺得不合適可以自己更改。只要按照上面的思路去一個一個的設置窗體最后肯定會獲得你想要的效果的。
在這里順便打一下小廣告^ ^,這個窗體皮膚的效果已經被我用在了我編寫的一個小軟件“上網計時小助手”上了,如果想看看皮膚的運用效果不妨去看看那個軟件哦!嘿嘿....軟件地址:http://www.rzrgm.cn/qianlifeng/archive/2010/05/03/1726801.html
好了,窗體部分經過3個部分的講解終于算是結束了。
相信大家對控件的編寫也有了一定的“感覺”了吧。這個窗體其實說起來還有一些地方不夠完善的,比如說窗體的起始位置沒有地方設置,再比如說當窗體上的控件太多的時候加載顯示窗體還是有一定程度上的不好的顯示現象的等等。這些缺點還只是我暫時發現的,肯定還有其他一些不好的地方就等待著細心而認真的你發現并去嘗試著解決它了。

在上一篇中,我們雖然已經做出界面大概的樣子出來了。不過還是存在著一些問題,包括運行緩慢和閃爍等一些問題。那么下面就讓我們一起來解決吧。
浙公網安備 33010602011771號