1. 程式人生 > >MFC學習之 背景貼圖及控制元件透明

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());
 }