问题是这样产生的.在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