双缓存的问题。

sad_4978 2006-04-05 04:30:49
最近在处理图形方面的东西在网上看到下面一段文字。
我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。
..........................
这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。

根据上面的解释,我试着做了一下,代码如下:
CBitmap m_bmTabBack;
m_bmTabBack.LoadBitmap(IDB_BITMAP1);

void CDoubleBufferDlg::OnPaint()
{

CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(&rect);
Draw(dc, rect);

CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap *pOld, bitmap;
bitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height());
pOld = memDC.SelectObject(&bitmap);
Draw(memDC, rect);
dc.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
memDC.SelectObject(pOld);
bitmap.DeleteObject();
memDC.DeleteDC();
}


void CDoubleBufferDlg::Draw(CDC& dc, RECT rect)
{

CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap *pOldBm = memDC.SelectObject(&m_bmTabBack);
dc.StretchBlt(rect.left, rect.top, rect.right - rect.left, 63, &memDC, 0, 7, 1, 63, SRCCOPY);
memDC.SelectObject(pOldBm);
memDC.DeleteDC();
}

大家看看这是双缓存了吧,我觉得是了。呵呵。(以前没有接触过,见笑了)

有两个问题不清楚。上面引用的文章中说“因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。”可是如果仔细的看,也能看到背景色。
还有就是,在OnPaint函数中使用BitBlt函数拷贝内存块,有些不理解。上面几句代码已经在画面上绘画了,然后又把一个缓冲区中的东西覆盖上,是什么意思呢?我知道这是双缓存,但是给我的感觉是应该是在用后台缓存中的内容来替代背景色清除显示区的动作。
请朋友帮忙解释一个下。
我描述的有些不清楚,主要是自己还不怎么清楚,呵呵。希望朋友们讲得详细些。谢谢。
...全文
660 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
wlwlxj 2006-04-05
  • 打赏
  • 举报
回复
OnEraseBkgnd()这个函数。使它直接返回TRUE,表示自己处理,呵呵
xundeng 2006-04-05
  • 打赏
  • 举报
回复
重载 OnEraseBkgnd()这个函数。使它直接返回FALSE。
这个函数是用来刷背景,每次客户区重绘都会先调用这个函数来刷新背景然后再绘制客户区
DentistryDoctor 2006-04-05
  • 打赏
  • 举报
回复
void CDoubleBufferDlg::Draw(CDC& dc, RECT rect)
{

CDC memDC;
memDC.CreateCompatibleDC(&dc);
CBitmap *pOldBm = memDC.SelectObject(&m_bmTabBack);
dc.StretchBlt(rect.left, rect.top, rect.right - rect.left, 63, &memDC, 0, 7, 1, 63, SRCCOPY);
memDC.SelectObject(pOldBm);
memDC.DeleteDC();
}

这个函数里面已经不用兼容DC与兼容位图了,已经dc到此其本身已经是兼容DC了。
wawaku 2006-04-05
  • 打赏
  • 举报
回复
呵,都有是DC,就是先画在一个非设备DC上(叫内存DC也好,反正就是画了不显示),等所有的画图操作都完成了,再一次性画到设备DC上,就OK了。说好听点叫双缓冲,实际上就是个拼DC的过程。
teli_eurydice 2006-04-05
  • 打赏
  • 举报
回复
全部绘制到 内存中再贴出来

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧