本帖解决的问题:
如何实现双缓冲 ?
为什么实现了双缓冲还是会闪烁?
以下资料为本人积累和加上自己的经验
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