int SetWindowRgn( HWND hWnd, HRGN hRgn, BOOL bRedraw );
其中hWnd為待設(shè)置的窗體句柄,hRgn為已經(jīng)創(chuàng)建的"region"句柄,bRedraw代表是否要重繪窗體。在MFC 中使用窗口類CWnd的成員函數(shù)int CWnd::SetWindowRgn(HRGN hRgn, BOOL bRedraw );該函數(shù)的參數(shù)意 義與API中同名函數(shù)相同。
相對與第二步,創(chuàng)建不規(guī)則窗體的第一步要復(fù)雜許多,并且不規(guī)則窗體越復(fù)雜,創(chuàng)建其"region"的過程也越復(fù)雜。接下去我們將由淺入深地介紹各種創(chuàng)建”region”的方法。
在MFC中"region"對象,由CRgn類實現(xiàn)。CRgn的幾乎每個成員函數(shù)都有同名的SDK API函數(shù)對應(yīng)。
三、簡單“region”的創(chuàng)建
類CRgn創(chuàng)建一個新的"region"的簡單方法有以下幾個成員函數(shù):
這里以創(chuàng)建橢圓窗體為例,介紹橢圓窗體創(chuàng)建的方法。在創(chuàng)建橢圓“region”的CreateEllipticRgn函數(shù)中,x1,y1指橢圓所在矩形的左上角坐標(biāo),x2,y2指該矩形的右下角坐標(biāo)。
下面的代碼加入到MFC對話框程序的OnInitDialog函數(shù)中,可將該對話框變成橢圓窗體:
BOOL CTestDlg::OnInitDialog(){ CDialog::OnInitDialog(); ... CRgn rgn; rgn. CreateEllipticRgn(0,0,200,100); SetWindowRgn(rgn,TRUE);}
BOOL CDC::BeginPath( );
調(diào)用該函數(shù)后當(dāng)前設(shè)備環(huán)境(DC)開始追蹤繪圖的過程。
int CDC::SetBkMode( int nBkMode );
設(shè)置繪圖時的背景模式,此應(yīng)用中nBkMode必須取值為TRANSPARENT 。即設(shè)置繪圖時背景不發(fā)生變化。
BOOL CDC::EndPath( );
調(diào)用該函數(shù)后當(dāng)前設(shè)備環(huán)境(DC)結(jié)束追蹤繪圖的過程。
開始繪圖前,先調(diào)用BeginPath,然后調(diào)用SetBkMode。接下去就可調(diào)用CDC的其他繪圖函數(shù)作圖,例如Arc,AngleArc,LineTo,MoveTo,RoundRect,,Textout等等。繪圖完畢調(diào)用EndPath().
第二步將繪制的結(jié)果轉(zhuǎn)成”region”.
此步驟中使用SDK API函數(shù)
HRGN PathToRegion( HDC hdc );
Hdc為作圖DC的句柄, CDC類中的m_hDC成員變量可做此參數(shù)傳入。示例,將下面代碼加入某個按鈕單擊事件中,可以將當(dāng)前窗體變?yōu)樽址県ello”的形狀
void CTestDlg::OnTest() { HRGN wndRgn; CClientDC dc(this); CFont mFont; if (dc.m_hDC!=NULL) { VERIFY(mFont.CreateFont( 200, 50, 0, 0, FW_HEAVY, TRUE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "宋體")); //開始記錄窗體輪廓路徑 dc.BeginPath(); //設(shè)置背景為透明模式,這句話是必須有的。 dc.SetBkMode(TRANSPARENT); CFont * pOldFont; pOldFont = dc.SelectObject( &mFont ); dc.TextOut(0, 0, "Hello"); //結(jié)束記錄窗體輪廓路徑 dc.SelectObject( pOldFont ); dc.EndPath(); //把所記錄的路徑轉(zhuǎn)化為窗體輪廓句柄 wndRgn = ::PathToRegion(dc.m_hDC); //賦予窗體指定的輪廓形狀 this->SetWindowRgn(wndRgn, TRUE); }}CClientDC是CDC的派生類,故此該類具有所有CDC類的成員變量和成員函數(shù)。
int CRgn::CombineRgn( CRgn* pRgn1, CRgn* pRgn2, int nCombineMode );
其中pRgn1,pRgn2為要合并的兩個“region”,nCombineMode為合并的方式,此應(yīng)用中取RGN_OR,即兩”region”全部合并去處重復(fù)部分。代碼實現(xiàn)如下:
void SetupRegion(CDC *pDC, //窗體的DC指針CBitmap &cBitmap, //含有窗體形狀的位圖對象COLORREF TransColor //透明色){ CDC memDC; //創(chuàng)建與傳入DC兼容的臨時DC memDC.CreateCompatibleDC(pDC); CBitmap *pOldMemBmp=NULL; //將位圖選入臨時DC pOldMemBmp=memDC.SelectObject(&cBitmap); CRgn wndRgn; //創(chuàng)建總的窗體區(qū)域,初始region為0 wndRgn.CreateRectRgn(0,0,0,0); BITMAP bit; cBitmap.GetBitmap (&bit);//取得位圖參數(shù),這里要用到位圖的長和寬 int y; for(y=0;y<=bit.bmHeight ;y++) { CRgn rgnTemp; //保存臨時region int iX = 0; do { //跳過透明色找到下一個非透明色的點. while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) == TransColor) iX++; //記住這個起始點 int iLeftX = iX; //尋找下個透明色的點 while (iX <= bit.bmWidth && memDC.GetPixel(iX, y) != TransColor) ++iX; //創(chuàng)建一個包含起點與重點間高為1像素的臨時“region” rgnTemp.CreateRectRgn(iLeftX, y, iX, y+1); //合并到主"region". wndRgn.CombineRgn(&wndRgn, &rgnTemp, RGN_OR); //刪除臨時"region",否則下次創(chuàng)建時和出錯 rgnTemp.DeleteObject(); }while(iX上述代碼創(chuàng)建的不規(guī)則窗體中,在OnEraseBkgnd事件中繪制該位圖,就可得到與該位圖形狀一模一樣的窗體。GetWindow(); pWnd->SetWindowRgn(wndRgn,TRUE); pWnd->SetForegroundWindow(); }