用VisualC 設計“精靈”窗體
- 發布于:2024-01-09
- 共 193 人圍觀
一、實現方法
一般情況下,實現異型窗體主要是作兩方面的工作,一是改變背景顏色,二是改變窗口外形。改變窗口背景顏色是最簡單的改變Windows應用程序外觀的方法,根據Windows創建與管理機理,一般有兩種方法。一種是處理WM_CTLCOLOR消息,需要重畫窗口或對話(或對話的子控件)時,Windows向應用程序發送消息WM_CTLCOLOR,應用程序處理WM_CTLCOLOR消息并返回一個用來繪畫窗體背景的刷子句柄。另外一種是響應Windows的WM_ERASEBKGND消息,Windows向窗口發送一個WM_ERASEBKGND消息通知該窗口擦除背景,可以使用VC 的ClassWizard重載該消息的缺省處理程序來擦除背景(實際是用刷子畫),并返回TRUE以防止Windows擦除窗口。對于改變窗體的外形,可以通過使用新的SDK函數SetWindowRgn(),將繪畫和鼠標消息限定在窗口的一個指定的區域,因此實際上是使窗口成為指定的不規則形狀(區域形狀)。"區域"是Windows GDI中一種強有力的機制,區域是設備上的一塊空間,可以是任意形狀,復雜的區域可以由各個小區域組合而成。Windows內含的區域創建函數有CreateRectRgn()、CreatePolyRgn()、CreatePolygonRgn()、CreateRoundRectRgn()和CreateEllipticRgn(),再通過CombineRgn()來組合區域,即可得到復雜形狀的區域,獲得復雜形狀的窗口外形。
通過上面的方法雖然可以得到"異形"窗口,但感覺顏色單調,外形也不夠"COOL",能否獲得更酷的"異形"窗口呢?回答是肯定的。下面就介紹利用位圖和蒙板創建"異形"窗口的方法。本實例實現的"精靈"效果就是通過這種方法實現的。
利用位圖創建異形窗體的原理是根據象素的顏色來進行"扣像"處理,對所有非指定顏色象素區域進行區域組合。利用這一技術,實際上就是實現對話框/窗口的位圖背景,并且對指定的顏色區域進行透明處理。下面就以透明位圖為背景的窗體為例來說明:
首先用繪圖軟件如PhotoShop繪制編輯一幅擬做程序背景用的圖片以及該圖片相應的掩模圖片,用BMP格式保存,下一步是用Visual C 的資源編輯器引入該背景圖片和掩模圖片文件,設置其ID為IDB_SHOW和IDB_MASK。需要說明的是,雖然Visual C 集成開發環境的資源編輯器只能編輯不超過16色的位圖,但完全我們可以以真彩色方式存儲,不必理會Visual C 的警告。
有了上述的工作,剩下的核心工作就是根據背景位圖和掩模位圖來確定最終顯示的位圖區域,也就是說,"扣除"的區域將以透明效果顯示。下面的代碼實現了這一功能:
/////////////////////////////////////////////////////////////////////////////
// 獲得窗體矩形
CRect rectWnd;
this->GetWindowRect(rectWnd);
// 讀取"掩模"位圖資源
CBitmap myBitmap,*pOldBitmap;
myBitmap.LoadBitmap(nMaskId);
// 創建"內存一致"設備
CDC memDC;
memDC.CreateCompatibleDC(pDC);
// 選擇繪圖設備
pOldBitmap = memDC.SelectObject(&myBitmap);
// 創建窗體的初始區域
CRgn rgnWnd,rgnTemp;
rgnWnd.CreateRectRgn(0,0,rectWnd.Width(),rectWnd.Height());
int nWidth,nHeight;
COLORREF color;
//下面的兩層循環為檢查背景位圖象素顏色,進行透明區域處理;
//當象素顏色為指定的透明值時,即將該點從區域中剪裁掉。
for (nWidth = 0;nWidth <= rectWnd.Width()-1;nWidth )
{
for (nHeight = 0;nHeight <= rectWnd.Height();nHeight )
{
color = memDC.GetPixel(nWidth,nHeight);
// 當象素是白色時,去掉該點
if (color == RGB(255,255,255))
{
//象素顏色為指定的透明色,創建透明"微區域"
rgnTemp.CreateRectRgn(nWidth,nHeight,nWidth 1,nHeight 1);
//"扣像",從完整的區域中"扣除"透明的"微區域"
rgnWnd.CombineRgn(&rgnWnd,&rgnTemp,RGN_XOR);
//刪除剛創建的透明"微區域",釋放系統資源
rgnTemp.DeleteObject();
}
}
}
memDC.SelectObject(pOldBitmap);
SetWindowRgn((HRGN)rgnWnd,TRUE); //用最終設定窗口的顯示區域為指定區域
為了最終顯示透明效果的窗體,還需要重置系統默認的背景擦除操作,即添加WM_ERASEBKGND消息處理過程,在其中實現背景位圖的顯示功能,這一步可以借助ClassWizard來實現。
最后需要注意的是,為了使異形窗體應用程序能夠正常地脫動和退出,需要處理窗體的WM_NCHITTEST、WM_CHAR等消息,這部分內容本書中其它實例已經作過介紹,這里就不再贅述了,感性趣的讀者朋友可以參考相關實例。
標簽: