關於OnEraseBkgnd和OnPaint的轉載

問題是這樣產生的.在OnEraseBkGnd中,若是你不調用原來缺省的OnEraseBkGnd只是重畫背景則不會有閃爍.而在OnPaint裏面,
因爲它隱含的調用了OnEraseBkGnd,而你又沒有處理OnEraseBkGnd 函數,這時就和窗口缺省的背景刷相關了.缺省的 OnEraseBkGnd操做使用窗口的缺省背景刷刷新背景(通常狀況 下是白刷),而隨後你又本身重畫背景形成屏幕閃動. 另一個問題是OnEraseBkGnd不是每次都會被調用的.若是你調用Invalidate的時候參數爲TRUE,那麼在OnPaint裏面隱含 調用BeginPaint的時候就產生WM_ERASEBKGND消息,若是參數是FALSE,則不會重刷背景.
 
因此解決方法有三個半:
1.用OnEraseBkGnd實現,不要調用原來的OnEraseBkGnd函數.
2.用OnPaint實現,同時重載OnEraseBkGnd,其中直接返回.
3.用OnPaint實現,建立窗口時設置背景刷爲空
4.用OnPaint實現,可是要求刷新時用Invalidate(FALSE)這樣
的函數.(不過這種狀況下,窗口覆蓋等形成的刷新仍是要閃一 下,因此不是完全的解決方法) 都挺簡單的.函數


在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() 可是若是咱們不呼叫的話,程序便不會畫上灰色的底色了it


比較好的作法是直接將繪圖的程序從OnPaint()移到OnEraseBkgnd()來作
以下所示io

// m_bmpBKGND 爲一CBitmap對象 且事先早已加載咱們的底圖
// 底圖的大小與咱們的窗口client大小一致function


BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
CRect rc;
GetUpdateRect(&rc);
CDC srcDC;
srcDC.CreateCompatibleDC(pDC);
srcDC.SelectObject(m_bmpBKGND);cli

pDC->BitBlt(rc.left,rc.top,rc.GetWidth(),
rc.GetHeight(),&srcDC,rc.left,rc.top,SRCCOPY);
return TRUE;
}date

特別要注意的是 取得重畫大小是使用GetUpdateRect() 而不是GetClientRect(),若是使用GetClientRect() 會把不應重畫的地方重畫.map

相關文章
相關標籤/搜索