http://hi.baidu.com/yuanzb/blog/item/1cb62401591f6d067bec2cec.html
在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() 會把不該重畫的地方重畫 |