地址:
在MFC中 任何一個window組件的繪圖 都是放在這兩個member function中
在設定上 OnEraseBkgnd()是用來畫底圖的 而OnPaint()是用來畫主要對象的
舉例說明 一個按鈕是灰色的上面還有文字
則OnEraseBkgnd()所做的事就是把按鈕畫成灰色
而OnPaint()所做的事就是畫上文字
既然這兩個member function都是用來畫出組件的
那為何還要分OnPaint() 與 OnEraseBkgnd() 呢
其實OnPaint() 與 OnEraseBkgnd() 特性是有差的:
1. OnEraseBkgnd()的要求是快速 在里面的繪圖程序最好是不要太耗時間因為每當window組件有任何小變動 都會馬上呼叫OnEraseBkgnd()
2. OnPaint() 是只有在程序有空閑的時候才會被呼叫
3. OnEraseBkgnd() 是在 OnPaint() 之前呼叫的
所以 OnPaint()被呼叫一次之前 可能會呼叫OnEraseBkgnd()好幾次
如果我們是一個在做圖形化使用者接口的人常會需要把一張美美的圖片設為我們dialog的底圖把繪圖的程序代碼放在OnPaint() 之中 可能會常碰到一些問題比方說拖曳一個窗口在我們做的dialog上面一直移動 則dialog會變成灰色 直到動作停止才恢復這是因為每次需要重繪的時候 程序都會馬上呼叫OnEraseBkgnd() OnEraseBkgnd()就把dialog畫成灰色而只有動作停止之后 程序才會呼叫OnPaint() 這時才會把我們要畫的底圖貼上去這個問題的解法 比較差點的方法是把OnEraseBkgnd() 改寫成不做事的function如下所示:
BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
以上本來是會呼叫CDialog::OnEraseBkgnd() 但是如果我們不呼叫的話程序便不會畫上灰色的底色了比較好的做法是直接將繪圖的程序從OnPaint()移到OnEraseBkgnd()來做如下所示:
// m_bmpBKGND 為一CBitmap物件且事先早已載入我們的底圖
// 底圖的大小與我們的視窗client大小一致
BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rc;
GetUpdateRect(&rc);
CDC srcDC;
srcDC.CreateCompatibleDC(pDC);
srcDC.SelectObject(m_bmpBKGND);
pDC->BitBlt(rc.left,rc.top,rc.GetWidth(),
rc.GetHeight(),&srcDC,rc.left,rc.top,SRCCOPY);
return TRUE;
}
特別要注意的是取得重畫大小是使用GetUpdateRect() 而不是GetClientRect()如果使用GetClientRect() 會把不該重畫的地方重畫