MFC學習之 背景貼圖及控制元件透明
在CDialog類中進行貼圖,一般放在OnPaint()函式中,因為視窗更新時,使用它來進行重繪。在OnPain()中貼圖的原始碼如下:
void C***Dialog::OnPaint() { CPaintDC dc(this); // device context for painting // CPaintDC dc(this); CRect rect; GetClientRect(&rect); CDC dcMem; //定義一個工具箱(裝置上下文) dcMem.CreateCompatibleDC(&dc);///建立關聯DC CBitmap bmpBackground; //點陣圖物件 bmpBackground.LoadBitmap(IDB_BITMAP_BKK); //IDB_BITMAP是你自己的圖對應的ID BITMAP bitmap; bmpBackground.GetBitmap(&bitmap); //建立繫結關係 CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground); //儲存原有CDC物件,並選入新CDC物件入DC dc.SetStretchBltMode(COLORONCOLOR);//防止bmp圖片失真 dc.StretchBlt(0,0,rect.Width(),rect.Height(),&dcMem,0,0, bitmap.bmWidth,bitmap.bmHeight,SRCCOPY); // (個人建議把,rect.Width(),rect.Height()這兩個資料 換成你的圖片的大小,前提是圖片足夠大,這樣圖片不容易失真。關於圖片失真,參考:http://blog.csdn.net/abidepan/article/details/7963929 ) dcMem.SelectObject(pbmpOld); bmpBackground.DeleteObject(); dcMem.DeleteDC(); }
當你貼圖完畢後,會發現很多地方出現了原來的底色,這是因為這是你的其他東東即控制元件,的畫刷沒有設定透明背景色。所有下一步就是設定透明背景色,程式碼如下:
HBRUSH C***Dialog::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CGraphDialog::OnCtlColor(pDC, pWnd, nCtlColor); if( nCtlColor == CTLCOLOR_STATIC) { pDC->SetBkMode(TRANSPARENT); //設定背景透明 return HBRUSH(GetStockObject(HOLLOW_BRUSH)); } return hbr; }
這兩個函式均為訊息響應函式,所以還需要新增訊息響應
.H檔案中
afx_msg void OnPaint();
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
CBrush m_brush;
.CPP檔案中
ON_WM_PAINT()
ON_WM_CTLCOLOR()
這個時候貼圖的效果就非常好了,但是你如果動態的修改靜態文字框控制元件內容時候,又發現了新的問題,發現字元可能重疊。這個原因是你在OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 函式中,將畫刷設定為透明引起的。那怎麼解決內,你就需要,在OnCtlColor(CDC*
pDC, CWnd* pWnd, UINT nCtlColor) 函式中返回一個具有背景的畫刷了。具體的辦法可以自己去琢磨,我這裡有個比較笨的辦法,給大家提供一個借鑑:
HBRUSH CAllMaterialDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if( nCtlColor == CTLCOLOR_STATIC)
{
pDC->SetBkMode(TRANSPARENT); //設定背景透明
// return HBRUSH(GetStockObject(HOLLOW_BRUSH));
hbr=(HBRUSH)(m_brush.GetSafeHandle());
}
return hbr;
}
有可能用到 Edit 控制元件時,而且用到時鐘控制元件在編輯框中顯示時間,這個時候又會出現文字重疊的問題。
1、//if (pWnd == GetDlgItem(IDC_EDIT_CAMERA_TIME))
//{
// UpdateWindow();
//}
2、// Invalidate(FALSE);
3、 //GetDlgItem(IDC_EDIT_CAMERA_TIME)->UpdateWindow();
4、//GetDlgItem(IDC_EDIT_CAMERA_TIME)->Invalidate(TRUE);
//GetDlgItem(IDC_EDIT_COMPUTERTIME)->Invalidate(TRUE);
都不管用!
------------------------------------------------------------------------------------------------------------------------
最令人糾結的應該是滑動條了!如果不做處理,就是這個樣子滴!
最後做出的效果是這樣滴:
也不怎麼好看,先把方法寫上來,以後再改好了。我自己也不知道怎麼就搞成這樣了 = =、
現在 Dlg::OnInitDialog()里加:
// 貼張圖
CBitmap m_Bitmap;
if(m_Bitmap.LoadBitmap(IDB_BITMAP_BKK))
{
m_brush.CreatePatternBrush(&m_Bitmap);
}
然後::OnPaint() 跟上面的一樣程式碼
再然後在Dlg::OnCtlColor里加:
if (pWnd == GetDlgItem(IDC_SLIDER_SPEED)) // IDC_SLIDER_SPEED是滑動條的ID
{
return (HBRUSH)m_brush.GetSafeHandle();
}
.....//這裡是各種控制元件的透明
pDC->SetBkMode(TRANSPARENT); //背景透明模式
return (HBRUSH)GetStockObject(NULL_BRUSH);
然後就成上面那樣了~
=======================================================================================================================
今天做另一個專案的UI,用到了 TabCtrl 這個控制元件,遇到了跟Slider類似的背景透明問題,然後分析了以前做Slider時的程式碼,知道了為什麼上面的控制元件背景顏色是那樣的了。
圖1
圖2
TabCtrl 這個控制元件跟 Slider 一樣 ,背景很難搞,在整個對話方塊貼了背景圖片之後的樣子 如 圖一
如果按Slider那樣做,也行
這次是把Dlg::OnInitDialog():裡的程式碼改成 m_brush.CreateSolidBrush(RGB(199, 199, 199));
其中 RGB(199, 199, 199) 其實就是 黑色區域附近的灰色 的顏色,然後在Dlg::OnCtlColor 返回畫刷的時候,返回這個顏色就行了。
對於一張顏色不太細緻的背景圖片來說,這樣做 如果不仔細看的話,是沒什麼問題的。
(後面的灰色是一張漸變的bmp圖片)
==============================================================================================================================
radiobutton的透明:checkbox也一樣。
在OnInitDialog() 裡:m_brush.CreateSolidBrush(RGB(199, 0, 0));
在OnCtlColor()裡:
if (pWnd->GetDlgCtrlID() == IDC_RADIO_ADMIN)
{
return (HBRUSH)(m_brush.GetSafeHandle());
}