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() 但是如果我们不呼叫的话,  程序便不会画上灰色的底色了.


比较好的做法是直接将绘图的程序从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() 会把不该重画的地方重画.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值