1. 程式人生 > >mfc 編輯框背景透明設定

mfc 編輯框背景透明設定

前幾天和風在這裡討論關於CEdit控制元件的透明問題。主要的目的就是要做一個有圖形背景的Edit控制元件,經過一番努,終於做出了一個還算象樣的Edit控制元件。 做一個透明的Edit控制元件的主要問題是字元的輸出,在Edit裡輸出的重新整理有幾個時機,一個是在接收到鍵盤或滑鼠訊息的時候 ,還有就是在接收到WM_PAINT訊息。重新整理的時候也不是全部重畫,所以想通過在繼承的Edit類中處理WM_PAINT訊息是行不通的。但是Edit控制元件自己總是知道怎麼去重新整理,因此只要給控制元件發訊息,讓其自己來重新整理就可以了。通過使用spy++的得知需要重新整理有幾個時機,一個是按鍵的時候,內容變化,另一個是選擇變化的時候,前者Edit控制元件會接收到GetCtlCode和KeyUp 訊息,後者會接收到GetCtlCode和CaptureChange訊息或KeyUp訊息,因此在GetCtlCode裡呼叫ReDrawWindow來強迫Edit重新整理 整個控制元件。在ReDrawWindow中通過使用引數RDW_ERASE可以使控制元件重畫背景,即呼叫OnEraseBkgnd(CDC* pDC),在該函式中重 畫背景。比較特殊的情況是按住滑鼠左鍵並來回拖動滑鼠的時候,這時候選擇要改變,接收的訊息是MouseMove,為了正 確響應也要處理該訊息,但是在每一個MouseMove中都重新整理顯示的開銷太大,而且不可避免地有閃爍感,因此只有在滑鼠左 鍵按下的時候才重新整理顯示。

大概的程式碼如下,主要是繼承了一個CEdit的物件CTpEdit,使用的時候可以動態建立,或者採用SubClass的方法。我用的是後者。

001.class CTESTDLG : public CDialog 002.{ 003....... 004.//宣告一個CTpEdit的成員變數 005.private: 006.CTpEdit m_tpedit; 007.}; 008. 009.//在OnInitDialog中Subclass對話方塊模板中的Edit控制元件 010.BOOL CTESTDLG::OnInitDialog()  011.{ 012.CDialog::OnInitDialog(); 013.
m_tpedit.SubclassDlgItem(IDC_EDIT,this); 014.return TRUE;  015.} 016. 017.//在OnCtlColor中設定背景的透明,要改變Edit控制元件字型的顏色也在這裡 018. 019.HBRUSH CTESTDLG::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)  020.{ 021.HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); 022. 023.if((nCtlColor == CTLCOLOR_EDIT) && (pWnd->GetDlgCtrlID()==IDC_EDIT))
024.{ 025.pDC->SetBkMode(TRANSPARENT); //設定背景透明,這樣,輸出字元的時候就 026.//是所謂的空心字,而不是有白的底色 027.pDC->SetTextColor(RGB(255,0,0)); //改變字型的顏色 028.return HBRUSH(GetStockObject(HOLLOW_BRUSH)); 029.} 030. 031.return hbr; 032.} 033. 034.//CTpEdit物件 035. 036.class CTpEdit : public CEdit 037.{ 038.public: 039.//m_mousedown用來記錄滑鼠左鍵是否按下 040.BOOL m_mousedown; 041.protected: 042.//響應如下的訊息 043.//{{AFX_MSG(CTpEdit) 044.afx_msg BOOL OnEraseBkgnd(CDC* pDC); 045.afx_msg void OnMouseMove(UINT nFlags, CPoint point); 046.afx_msg void OnLButtonDown(UINT nFlags, CPoint point); 047.afx_msg void OnLButtonUp(UINT nFlags, CPoint point); 048.afx_msg UINT OnGetDlgCode(); 049.//}}AFX_MSG 050.DECLARE_MESSAGE_MAP() 051.}; 052. 053.//CTpEdit的訊息響應函式如下 054.//畫背景圖 055.BOOL CTpEdit::OnEraseBkgnd(CDC* pDC)  056.{ 057.//得到Edit控制元件的外框,即背景區域 058.RECT updatarect;  059.GetClientRect(&updatarect); 060.//畫背景,我畫的是一個黃色的矩形 061.CBrush newBrush; 062.newBrush.CreateSolidBrush(RGB(255,255,200)); 063.CBrush * oldBrush = pDC->SelectObject(&newBrush); 064.pDC->Rectangle(&updatarect); 065.pDC->SelectObject(oldBrush); 066.return TRUE; 067.} 068. 069.//強迫Edit控制元件擦除背景,重寫字元 070.UINT CTpEdit::OnGetDlgCode()  071.{ RedrawWindow(NULL, NULL,RDW_INVALIDATE | RDW_ERASE );  072.return CEdit::OnGetDlgCode(); 073.} 074.//記錄滑鼠左鍵是否按下 075.void CTpEdit::OnLButtonDown(UINT nFlags, CPoint point)  076.{ 077.m_mousedown = TRUE; 078.SetCapture(); 079.CEdit::OnLButtonDown(nFlags, point); 080.} 081. 082.void CTpEdit::OnLButtonUp(UINT nFlags, CPoint point)  083.{ 084.if(m_mousedown)  085.ReleaseCapture(); 086.m_mousedown = FALSE; 087.CEdit::OnLButtonUp(nFlags, point); 088.} 089. 090.//如果左鍵按下並且拖動滑鼠就要重新整理顯示 091.void CTpEdit::OnMouseMove(UINT nFlags, CPoint point) 092.{ 093.if(m_mousedown) 094.RedrawWindow(NULL, NULL,RDW_INVALIDATE | RDW_ERASE ); 095.CEdit::OnMouseMove(nFlags, point); 096.} 097.//初始化成員變數 098.CTpEdit::CTpEdit() 099.{ 100.m_mousedown=FALSE; 101.}