用VC++實(shí)現(xiàn)不規(guī)則窗口
隨著Windows95的推出,在PC系統(tǒng)中出現(xiàn)了越來越多的應(yīng)用程序采用了非矩形外觀的窗體,或者模擬現(xiàn)實(shí)中的事物,如鐘、眼睛等;或者創(chuàng)造一個(gè)具有三維觀感的非現(xiàn)實(shí)物體,這類程序以各種mp3播放器為代表,甚至一些大腕級(jí)的老牌應(yīng)用程序(如Norton),也開始擁有這種窗口。一來是因?yàn)?a class="channel_keylink" target="_blank">Windows操作系統(tǒng)和各類開發(fā)工具自身功能的極大提升;二來,也說明開發(fā)人員希望通過與眾不同的外觀,來強(qiáng)調(diào)使用時(shí)的第一映像,以期達(dá)到吸引用戶的目的,畢竟,現(xiàn)在的PC是一個(gè)充滿圖形(圖象)的世界,充分利用這一特點(diǎn),也能在一定程度上改善程序界面的可操作性。而且,對(duì)于同一類型的應(yīng)用程序,在功能、性能相差不大的情況下,用戶也往往愿意選擇外觀漂亮的那種。因而,很多文章都在介紹如何創(chuàng)建不規(guī)則的窗口,但幾乎千篇一律地基于VB進(jìn)行說明。而筆者本人一直基于C/C++語(yǔ)言進(jìn)行開發(fā),因此,研究了一下在VC++5中實(shí)現(xiàn)不規(guī)則窗口的方法,下面就實(shí)現(xiàn)的主要方法進(jìn)行說明。
VC++5提供了CRgn類和SetWindowRgn()函數(shù)來實(shí)現(xiàn)不規(guī)則的程序窗口。創(chuàng)建一個(gè)不規(guī)則窗口的過程是:首先定義一個(gè)CRgn類,并用各種初始化函數(shù)創(chuàng)建CRgn類的具體區(qū)域,然后調(diào)用CWnd::SetWindowRgn()函數(shù)創(chuàng)建不規(guī)則窗口。
CRgn是從CgdiObject衍生出來的類,用來確定一個(gè)多邊形、橢圓或者由多邊形及橢圓合成的范圍,在程序中主要會(huì)用到CreateRectRgnIndirect()、CreateEllipticRgnIndirect()、CreatePolygonRgn()三個(gè)函數(shù)。
CreateRectRgnIndirect(LPCRECT
lpRect)函數(shù)創(chuàng)建一個(gè)矩形區(qū)域,參數(shù)lpRect指定所創(chuàng)建的矩形區(qū)域在窗口用戶區(qū)中的left(左)、top(上)、right(右)、bottom(下)坐標(biāo)。例如:
CRgn MyRgn;
RECT m_rect;
m_rect.left=0; m_rect.top=0; m_rect.right=500; m_rect.bottom=300;
MyRgn.CreateRectRgnIndirect( &m_rect );
CreateEllipticRgnIndirect(LPCRECT
lpRect)函數(shù)創(chuàng)建一個(gè)橢圓形區(qū)域,參數(shù)lpRect指定所創(chuàng)建的橢圓形區(qū)域在窗口用戶區(qū)中的left(左)、top(上)、right(右)、bottom(下)坐標(biāo),如果指定right坐標(biāo)與left坐標(biāo)之差等于bottom坐標(biāo)與top坐標(biāo)之差,則創(chuàng)建的區(qū)域是一個(gè)圓。例如:
CRgn MyRgn;
RECT m_rect;
m_rect.left=0; m_rect.top=0; m_rect.right=500; m_rect.bottom=300;
MyRgn.CreateEllitpticRgnIndirect( &m_rect );
CreatePolygonRgn(LPPOINT lpPoints, int nCount, int
nMode)函數(shù)創(chuàng)建一個(gè)多邊形區(qū)域,參數(shù)lpPoints指向一個(gè)POINT結(jié)構(gòu)數(shù)組,在POINT結(jié)構(gòu)數(shù)組中每個(gè)POINT結(jié)構(gòu)項(xiàng),用來確定多邊形頂點(diǎn)在窗口用戶區(qū)中的坐標(biāo);nCount說明POINT結(jié)構(gòu)數(shù)組中POINT結(jié)構(gòu)項(xiàng)的數(shù)目,也就是多邊形的頂點(diǎn)數(shù);nMode指定多邊形的填充方式,一般使用ALTERNATE方式。例如創(chuàng)建一個(gè)三角形:
CRgn MyRgn;
POINT Points;
Points[0].x=Points[0].y=0; Points.x=10; Points.y=30; Points.x=5; Points.y=60;
MyRgn.CreatePolygonRgn(Points, 3, ALTERNATE);
利用以上的函數(shù)創(chuàng)建區(qū)域后,就可以調(diào)用CWnd::SetWindowRgn(HRGN hRgn, BOOL
bRedraw)來創(chuàng)建非矩形的窗口了。SetWindowRgn()函數(shù)參數(shù)說明:hRgn是一個(gè)CRgn類的句柄;bRedraw如果被設(shè)置成TRUE,那么,在窗口次序發(fā)生變化時(shí),系統(tǒng)會(huì)發(fā)送WM_WINDOWPOSCHANGING和WM_WINDOWPOSCHANGED消息給窗口。
如果要?jiǎng)?chuàng)建外形更復(fù)雜的窗口,例如mp3播放器Soniq的一個(gè)播放界面,就是兩個(gè)圓形部分重合形成的。對(duì)于這類窗口的創(chuàng)建,還要用到CRgn類另外一個(gè)極其重要的函數(shù)——CombineRgn()。首先要說明的是:在VC++5的在線幫助中,將這個(gè)函數(shù)歸入了初始化(Initialization)類型中,實(shí)際上,如果定義的CRgn類在沒有使用其它初始化函數(shù)初始化之前,就調(diào)用這個(gè)函數(shù)的話,程序?qū)?huì)失敗,所以,這個(gè)函數(shù)似乎應(yīng)該歸入operation類更恰當(dāng)。
CombineRgn(CRgn* pRgn1, CRgn* pRgn2, int
nCombineMode)函數(shù)用來創(chuàng)建一個(gè)由多個(gè)多邊形、橢圓合成的不規(guī)則區(qū)域。pRgn1、pRgn2分別指向參與合成不規(guī)則區(qū)域的多邊形或橢圓形;nCombineMode說明合成的方式:RGN_AND最后的區(qū)域是pRgn1和pRgn2的重疊部分;RGN_DIFF最后的區(qū)域是pRgn1中不包含pRgn2的部分;RGN_OR最后的區(qū)域同時(shí)包含pRgn1和pRgn2;RGN_XOR最后的區(qū)域同時(shí)包含pRgn1和pRgn2,但不包含pRng1和pRng2重疊的部分。例如,創(chuàng)建一個(gè)類似Soniq播放器的界面:
......
RECT m_Cyc1;
RECT m_Cyc2;
CRgn RgnCyc1;
CRgn RgnCyc2;
CRgn RgnDlg;
m_Cyc1.left=100; m_Cyc1.top=5; m_Cyc1.right=200; m_Cyc1.bottom=105;
m_Cyc2.left=80; m_Cyc2.top=85; m_Cyc2.right=180; m_Cyc2.bottom=185;
RgnDlg.CreateEllipticRgnIndirect( &m_Cyc1 );
RgnCyc1.CreateEllipticRgnIndirect( &m_Cyc1 );
RgnCyc2.CreateEllipticRgnIndirect( &m_Cyc2 );
RgnDlg.CombineRgn( &RgnCyc1, &RgnCyc2, RGN_OR );
MyWin.SetWindowRgn( (HRGN)RgnDlg, TURE );
......
以上就是利用VC++5實(shí)現(xiàn)不規(guī)則窗口的方法,相信大家看后都能創(chuàng)造出各種希奇古怪的窗口來,但是,有一點(diǎn)應(yīng)該提請(qǐng)注意:對(duì)于Windows操作系統(tǒng)而言,桌面上窗口的形狀存儲(chǔ)在內(nèi)存中,所以,窗口外形的復(fù)雜程度應(yīng)該適可而止,不要超過32767╳32767個(gè)邏輯單元,或者64K存儲(chǔ)區(qū)
。當(dāng)然,還有一點(diǎn)很重要:就是給窗口一張漂亮的臉,最好具有三維立體效果。
曾勁峰
聯(lián)系客服