靜態控件也是比較常用的控件,在VS開發環境中用的應該挺頻繁的吧。
其實mfc中實現對窗口美化,主要依賴於重繪。static控件也是個窗口,windows爲其留有自繪的權利,可以設置其樣式爲SS_OWNERDRAW,Windows就會把其繪製權利交給我們的代碼,怎麼繪製就看我們的代碼了。mfc中更好的一種方式就是消息反射,省的自己來做這一步操作了,我們重載CStatic中的DrawItem方法,進行自繪,基本就可以了。其實如果自己在OnPaint裏畫也是可以的(對於任何控件窗口都可以的,只是麻煩或者有其他的問題)。
我們可以給CStatic中加入背景圖片,畫成按鈕樣式,等等,可以模擬出其他的控件(像CButton),如果CStatic要響應事件我們可以加上SS_NOTIFY樣式,這樣父窗口就會把消息傳遞到CStatic裏面來,要怎麼處理就看我們了。
下面看下具體怎麼做:
第一要設置繼承CStatic類,我們自己寫一個Static類,我給他起了CSkinStatic的名字。
第二,設置其樣式爲SS_OWNERDRAW,設置樣式可以在Static控件創建前後都可以,但要在其顯示前,我這裏在CSkinStatic::PreSubclassWindow()中進行設置
- void CSkinStatic::PreSubclassWindow()
- {
- // TODO: 在此添加專用代碼和/或調用基類
- DWORD dwStyle = GetStyle();
- SetWindowLong(GetSafeHwnd(),GWL_STYLE,dwStyle | SS_OWNERDRAW );
- CStatic::PreSubclassWindow();
- }
第三,就是重載DrawItem,然後在裏面想怎麼畫就怎麼畫了。
- void CSkinStatic::DrawItem(LPDRAWITEMSTRUCT )
- {
- CRect rcWnd;
- GetWindowRect(&rcWnd);
- ScreenToClient(&rcWnd);
- CString strText;
- GetWindowText(strText);
- CBitmap bmp;
- bmp.LoadBitmap(IDB_BITMAP1);
- BITMAP bmpInfo;
- bmp.GetBitmap(&bmpInfo);
- CDC *pdc = GetWindowDC();
- CDC dcMem;
- dcMem.CreateCompatibleDC(pdc);
- CBitmap bmpBg;
- bmpBg.CreateCompatibleBitmap(pdc,rcWnd.Width(),rcWnd.Height());
- dcMem.SelectObject(&bmpBg);
- CDC dcDraw;
- dcDraw.CreateCompatibleDC(pdc);
- dcDraw.SelectObject(&bmp);
- dcMem.StretchBlt(0,0,rcWnd.Width(),rcWnd.Height(),&dcDraw,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY);
- CFont font;
- VERIFY(font.CreateFont(
- 12, // nHeight
- 0, // nWidth
- 0, // nEscapement
- 0, // nOrientation
- FW_NORMAL, // nWeight
- FALSE, // bItalic
- FALSE, // bUnderline
- 0, // cStrikeOut
- ANSI_CHARSET, // nCharSet
- OUT_DEFAULT_PRECIS, // nOutPrecision
- CLIP_DEFAULT_PRECIS, // nClipPrecision
- DEFAULT_QUALITY, // nQuality
- DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
- "宋體")); // lpszFacename
- dcMem.SelectObject(&font);
- dcMem.SetBkMode(TRANSPARENT);
- dcMem.SetTextColor(RGB(255,0,0));
- dcMem.DrawText(strText,&rcWnd,DT_CENTER);
- //pdc->BitBlt(0,0,rcWnd.Width(),rcWnd.Height(),&dcMem,0,0,SRCCOPY);
- //pdc->TransparentBlt(0,0,rcWnd.Width(),rcWnd.Height(),&dcMem,0,0,rcWnd.Width(),rcWnd.Height(),RGB(255,0,0));
- BLENDFUNCTION bf = {0};
- bf.AlphaFormat = AC_SRC_OVER ;
- bf.BlendFlags = 0;
- bf.BlendOp = AC_SRC_OVER ;
- bf.SourceConstantAlpha = 125;
- pdc->AlphaBlend(0,0,rcWnd.Width(),rcWnd.Height(),&dcMem,0,0,rcWnd.Width(),rcWnd.Height(),bf);
- bmp.DeleteObject();
- ReleaseDC(pdc);
- }
這個繪圖稍有點麻煩,大致是這樣的 先創建內存兩個內存DC一個作爲畫布,另一個負責引入圖片,再拉伸拷貝到畫布DC上,最後畫布DC全部拷貝到窗口DC上。這主要是防止貼圖和寫文字不同步,造成有圖無字,也避免了一個內存DC造成的字體拉伸。運用了網上盛傳的雙緩衝。
經過我們自己的代碼處理後,可以看看Static成什麼樣了
當然可以自己畫個漸變色出來。不過個人覺得還是貼圖方便。
Static控件的美化比較簡單,沒有什麼多的消息要進行處理。不過要想設置個性的,也得需要幾個狀態變量,多個圖片吧。
基本的東西都很好做,如果想做好點細膩點,總會有點麻煩的。
HUGO:通過查看msdn: VC6.0並不支持CStatic的自繪。VC2005和VC2008都支持