本帖解决的问题:
如何实现双缓冲 ?
为什么实现了双缓冲还是会闪烁?
以下资料为本人积累和加上自己的经验
1、简介一下windows mfc的view显示刷新过程:
(1)、使用背景刷填充view窗体(调用内在机制的);(2)、调用OnPain()\OnDraw(调用用户的);
2、产生闪烁的原因出在于
:当我们很快地刷新view时,都要执行以上两步,而使用背景刷时是实时填充的(本人猜想的),所以效率
很低,于是造成执行以上两步时的时间比人眼的响应时间要长,从而出现了闪烁。
3、解决方案:
我们可以这样想,mfc自动调用背景刷是为了去除旧的信息,然后让用户加上新的信息(调用OnPain或OnDraw),那么我们就
把这两步都自己做吧。其实这两步我们可以合一,简单来说就是我们先在一块内存里面先把东西画好,然后将它直接复制到view,内存复制是
速度很快的,当然我们把背景先要在这快内存里面填充好,这样我们就在这块内存里面都把这两步都搞好了,最后一步就是把它复制到显示的
buffer里面了;
4、具体方法:
先生成一个view窗体:
1)、增加
成员变量
:
CBitmap* m_pBitmap;
//这就是内存里面的画布了
CDC* m_pMemDC;
//这就是用于绘制这块内存的画笔
int
m_nScreenY;
//这个画布的高
int m_nScreenX;
//这个画布的宽
2)、然后在view的
【构造函数】里面
添加以下代码(这里就不注析了,会c++的人都懂):
m_pMemDC=new CDC;
m_pBitmap=new CBitmap;
m_nScreenY=1024;
m_nScreenX=1280;
3)、然后增加消息响应【WM_CREATE】:
添加:
CDC*pDC=GetDC();
m_pMemDC->CreateCompatibleDC(pDC);
//创建内存dc
m_pBitmap->CreateCompatibleBitmap(pDC,m_nScreenX,m_nScreenY);
//创建内存画布
//
m_pBitmap->LoadBitmap(MAKEINTRESOURCE(IDB_BITMAP1));
//你甚至可以用你的资源位图作为画布
CBitmap*pOldBitmap=m_pMemDC->SelectObject(m_pBitmap);
//让m_pMemDC知道要绘制哪块内存
CBrush brush(RGB(255,255,255));
CRect rect;
GetClientRect(rect);
m_pMemDC->FillRect(CRect(rect.left,rect.top,m_nScreenX,m_nScreenY),&brush);
//这里相当于我们完成了背景刷
m_pMemDC->SelectObject(pOldBitmap);
ReleaseDC (pDC);
4)、
在OnDraw()里面添加:
CRect rect;
GetClientRect(rect);
//获取当前用户区的大小
CBitmap*pOldBitmap=m_pMemDC->SelectObject(m_pBitmap);
DrawSomething();//这里加入你要画的东西
pDC->BitBlt (rect.left ,rect.top ,m_nScreenX,m_nScreenY,m_pMemDC,rect.left ,rect.top ,SRCCOPY);
//这里就是将内存里面的
画布复制到显示设备的buffer了
m_pMemDC->SelectObject(pOldBitmap);
5)、以上其实是完成了双缓冲机制了,但如果你高速地调用Invalidate();时,还是会感到很闪烁的,why?我们
忘记去掉内在的背景刷了
,要去掉也是超简单:
添加消息响应:WM_ERASEBKGND,然后在这个响应函数里面添加return true;//(记得在return CView::OnEraseBkgnd(pDC);之上)
6)、大功告成
当然new 了的东西还要delete ,在析构函数里面再增加:
delete m_pBitmap;
delete m_pMemDC;
7)、如何DrawSomething()
void DrawSomething()
{
CBitmap*pOldBitmap=m_pMemDC->SelectObject(m_pBitmap);
m_pMemDC->Rectangle(0,0,100,100);
//画你想画的
m_pMemDC->SelectObject(pOldBitmap);
Invalidate();
}
5、小结:
想当年(也就一年前),这个东西困扰了我很久了,现在翻出来,为了后来者看看,少走些弯道,高手可以不用理了。
整理by Letterb @scnu_cs_05
Email:
letterb@tom.com