隨著Windows95的推出,在PC系統中出現了越來越多的應用程式採用了非矩形外觀的表單,或者類比現實中的事物,如鐘、眼睛等;或者創造一個具有三維觀感的非現實物體,這類程式以各種mp3播放器為代表,甚至一些大腕級的老牌應用程式(如Norton),也開始擁有這種視窗。一來是因為Windows作業系統和各類開發工具自身功能的極大提升;二來,也說明開發人員希望通過與眾不同的外觀,來強調使用時的第一映像,以期達到吸引使用者的目的,畢竟,現在的PC是一個充滿圖形(圖象)的世界,充分利用這一特點,也能在一定程度上改善程式介面的可操作性。而且,對於同一類型的應用程式,在功能、效能相差不大的情況下,使用者也往往願意選擇外觀漂亮的那種。因而,很多文章都在介紹如何建立不規則的視窗,但幾乎千篇一律地基於VB進行說明。而筆者本人一直基於C/C++語言進行開發,因此,研究了一下在VC++5中實現不規則視窗的方法,下面就實現的主要方法進行說明。
VC++5提供了CRgn類和SetWindowRgn()函數來實現不規則的程式視窗。建立一個不規則視窗的過程是:首先定義一個CRgn類,並用各種初始化函數建立CRgn類的具體地區,然後調用CWnd::SetWindowRgn()函數建立不規則視窗。
CRgn是從CgdiObject衍生出來的類,用來確定一個多邊形、橢圓或者由多邊形及橢圓合成的範圍,在程式中主要會用到CreateRectRgnIndirect()、CreateEllipticRgnIndirect()、CreatePolygonRgn()三個函數。
CreateRectRgnIndirect(LPCRECT
lpRect)函數建立一個矩形地區,參數lpRect指定所建立的矩形地區在視窗使用者區中的left(左)、top(上)、right(右)、bottom(下)座標。例如:
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)函數建立一個橢圓形地區,參數lpRect指定所建立的橢圓形地區在視窗使用者區中的left(左)、top(上)、right(右)、bottom(下)座標,如果指定right座標與left座標之差等於bottom座標與top座標之差,則建立的地區是一個圓。例如:
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)函數建立一個多邊形地區,參數lpPoints指向一個POINT結構數組,在POINT結構數組中每個POINT結構項,用來確定多邊形頂點在視窗使用者區中的座標;nCount說明POINT結構數組中POINT結構項的數目,也就是多邊形的頂點數;nMode指定多邊形的填充方式,一般使用ALTERNATE方式。例如建立一個三角形:
CRgn MyRgn;
POINT Points[3];
Points[0].x=Points[0].y=0; Points[1].x=10; Points[1].y=30; Points[2].x=5; Points[2].y=60;
MyRgn.CreatePolygonRgn(Points, 3, ALTERNATE);
利用以上的函數建立地區後,就可以調用CWnd::SetWindowRgn(HRGN hRgn, BOOL
bRedraw)來建立非矩形的視窗了。SetWindowRgn()函數參數說明:hRgn是一個CRgn類的控制代碼;bRedraw如果被設定成TRUE,那麼,在視窗次序發生變化時,系統會發送WM_WINDOWPOSCHANGING和WM_WINDOWPOSCHANGED訊息給視窗。
如果要建立外形更複雜的視窗,例如mp3播放器Soniq的一個播放介面,就是兩個圓形部分重合形成的。對於這類視窗的建立,還要用到CRgn類另外一個極其重要的函數――CombineRgn()。首先要說明的是:在VC++5的線上協助中,將這個函數歸入了初始化(Initialization)類型中,實際上,如果定義的CRgn類在沒有使用其它初始化函數初始化之前,就調用這個函數的話,程式將會失敗,所以,這個函數似乎應該歸入operation類更恰當。
CombineRgn(CRgn* pRgn1, CRgn* pRgn2, int
nCombineMode)函數用來建立一個由多個多邊形、橢圓合成的不規則地區。pRgn1、pRgn2分別指向參與合成不規則地區的多邊形或橢圓形;nCombineMode說明合成的方式:RGN_AND最後的地區是pRgn1和pRgn2的重疊部分;RGN_DIFF最後的地區是pRgn1中不包含pRgn2的部分;RGN_OR最後的地區同時包含pRgn1和pRgn2;RGN_XOR最後的地區同時包含pRgn1和pRgn2,但不包含pRng1和pRng2重疊的部分。例如,建立一個類似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實現不規則視窗的方法,相信大家看後都能創造出各種希奇古怪的視窗來,但是,有一點應該提請注意:對於Windows作業系統而言,案頭上視窗的形狀儲存在記憶體中,所以,視窗外形的複雜程度應該適可而止,不要超過32767?w32767個邏輯單元,或者64K儲存區
。當然,還有一點很重要:就是給視窗一張漂亮的臉,最好具有三維立體效果。
曾勁峰
一九九年五月