松鼠的博客

导航

统计

OnPaint与OnEraseBkgnd

 

OnPaint()OnEraseBkgnd()

地址:

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() 會把不該重畫的地方重畫

posted on   Xproer-松鼠  阅读(2080)  评论(0编辑  收藏  举报

编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示