一、简介

在进行复杂图形绘制时,若直接在屏幕DC上进行绘制,则会出现明显的闪烁。闪烁产生的原因是当绘制的图形较为 复杂时,图形绘制过程中就被刷新到屏幕上,导致结果断断续续地显示出来。双缓冲绘图的原理是在另开辟一块内存用于绘制,当所有绘制工作完成后将内存数据一 次性拷贝到屏幕上。

双缓冲绘图步骤:

创建兼容DC(CreateCompatibleDC)

创建兼容位图(CreateCompatibleBitmap)

将兼容位图选入兼容DC(SelectObject)

在兼容DC中进行绘制工作

将兼容DC中的像素拷贝至屏幕DC(BitBlt)

从兼容DC中换出兼容位图(SelectObject)

删除兼容位图(DeleteObject)

删除兼容DC(DeleteObject)

二、实现:

演示程序绘制了从窗口中心发射的300条射线,为了凸显双缓冲的效果,特意在绘制每条线段时添加延时操作(sleep)。可以发现,若直接在屏幕DC上绘制,能够明显感觉到每条线段的绘制过程,而采用双缓冲则无此现象。

直接绘制代码:

void CtestBFDlg::OnBnClickedDirectDraw()
{
// TODO: 在此添加控件通知处理程序代码
CPen newPen;
CPen *pOldPen;
CBrush newBrush;
CBrush *pOldBrush;
CRect zcRect;
CDC *pDc;
CPoint cenpoint;
CPoint point; pDc = Picture.GetDC();
Picture.GetClientRect(&zcRect);
newPen.CreatePen(PS_SOLID,,RGB(,,));//画笔
pOldPen = pDc->SelectObject(&newPen);
newBrush.CreateSolidBrush(RGB(,,));//画刷
pOldBrush=pDc->SelectObject(&newBrush); //绘制工作(直接在屏幕DC上作图)
pDc->FillRect(zcRect,&newBrush);
float radius=;
float degree=;
float x,y;
float cenx,ceny;
cenx=zcRect.Width()/2.0;
ceny=zcRect.Height()/2.0;
cenpoint.x=cenx;
cenpoint.y=ceny;
for(int i=;i<;i++)
{
pDc->MoveTo(cenpoint);
degree=*PI/*i;
point.x=radius*cos(degree)+cenx;
point.y=radius*sin(degree)+ceny;
Sleep(); //刻意延时以凸显效果
pDc->LineTo(point);
}
pDc->SelectObject(pOldPen);
pDc->SelectObject(pOldBrush);
newBrush.DeleteObject();
newPen.DeleteObject();
ReleaseDC(pDc);
}

双缓冲绘制代码:

void CtestBFDlg::OnBnClickedDFDraw()
{
// TODO: 在此添加控件通知处理程序代码
CPen newPen;
CPen *pOldPen;
CBrush newBrush;
CBrush *pOldBrush;
CRect zcRect;
CDC *pDc;
CPoint cenpoint;
CPoint point;
pDc = Picture.GetDC();
Picture.GetClientRect(&zcRect); CDC dc;
dc.CreateCompatibleDC(pDc);//创建兼容DC
CBitmap memBmp;
memBmp.CreateCompatibleBitmap(pDc, zcRect.Width(), zcRect.Height());//创建兼容位图
CBitmap* OldBmp = dc.SelectObject(&memBmp);//将位图选入DC newPen.CreatePen(PS_SOLID,,RGB(,,));
pOldPen = dc.SelectObject(&newPen);
newBrush.CreateSolidBrush(RGB(,,));
pOldBrush=dc.SelectObject(&newBrush); //绘制工作(在兼容DC中作图)
//****************************************************************
dc.FillRect(zcRect,&newBrush);
float radius=;
float degree=;
float x,y;
float cenx,ceny;
cenx=zcRect.Width()/2.0;
ceny=zcRect.Height()/2.0;
cenpoint.x=cenx;
cenpoint.y=ceny;
for(int i=;i<;i++)
{
dc.MoveTo(cenpoint);
degree=*PI/*i;
point.x=radius*cos(degree)+cenx;
point.y=radius*sin(degree)+ceny;
Sleep(); //此处刻意延时以凸显效果
dc.LineTo(point);
}
//****************************************************************
pDc->BitBlt(,,zcRect.Width(),zcRect.Height(),&dc,,,SRCCOPY);//将兼容DC中位图拷贝至屏幕DC
dc.SelectObject(pOldPen);
dc.SelectObject(pOldBrush);
dc.SelectObject(OldBmp);
newBrush.DeleteObject();
newPen.DeleteObject();
memBmp.DeleteObject();
dc.DeleteDC();
ReleaseDC(pDc);
}

界面:

源码下载

GDI双缓冲绘图的更多相关文章

  1. C#-gdi绘图,双缓冲绘图,Paint事件的触发

    一. 画面闪烁问题与双缓冲技术 1.1 导致画面闪烁的关键原因分析: 1  绘制窗口由于大小位置状态改变进行重绘操作时 绘图窗口内容或大小每改变一次,都要调用Paint事件进行重绘操作,该操作会使画面 ...

  2. 陈灯WGF双缓冲绘图框架

    “木丸子童屋”,专售各类儿童玩具,价格优惠,请大家多多支持:http://shop65552598.taobao.com/ WGF(windows graphic foundation)为window ...

  3. mfc双缓冲绘图

    1.要求 在界面加载本地图片并显示,每过100ms改变一张图片显示 2.现象 通过定时器控制CImage,Load,Draw,Destroy,会非常的卡顿.因为Load图片时,会是非常大的数据[所有C ...

  4. C# GDI+双缓冲技术

    我想有很多搞图形方面的朋友都会用到双缓冲技术的时候,而且有的时候她的确是个头疼的问题.最近我也要用双缓冲技术,程序怎么调试都不合适,当要对图形进行移动时,总是会出现闪烁抖动.在网上找了些资料,说得都不 ...

  5. MFC双缓冲绘图(2015.09.24)

    问题引入: 最近在尝试编写贪吃蛇游戏时遇到这么一个问题:当系统以较快频率向窗口发送WM_PAINT消息时,调用OnPaint()函数在窗口中绘制图形就会发生闪烁现象. 问题分析: 当我们把绘图过程放在 ...

  6. MFC双缓冲绘图实例

    本人之前一直了解双缓冲绘图的基本原理,但是在研究很久之后才大概知道具体的使用过程,本文将详细介绍本人在实际项目中使用双缓冲绘图的案例. 实现功能:主界面显示某张包含人脸的图片,通过dlib detec ...

  7. 双缓冲绘图和窗口控件的绘制——ATL ActiveX 窗口控件生成向导绘制代码OnDraw的一个错误 .

    双缓冲绘图和窗口控件的绘制 ---ATL ActiveX 窗口控件生成向导绘制代码OnDraw的一个错误 cheungmine 我们通常使用ATL COM组件,生成一个带窗口的ActiveX控件,然后 ...

  8. 简单的 "双缓冲" 绘图的例子(研究一下)

    所谓双缓冲就是先画到内存画布(如: TBitmap), 然后再转帖到目的地. 譬如下面小程序: procedure TForm1.FormCreate(Sender: TObject); begin ...

  9. 【MFC】MFC绘制动态曲线,用双缓冲绘图技术防闪烁

    摘自:http://zhy1987819.blog.163.com/blog/static/841427882011614103454335/ MFC绘制动态曲线,用双缓冲绘图技术防闪烁   2011 ...

随机推荐

  1. CString转换成char *字符串问题

    buf = (LPSTR)(LPCTSTR)str;      ==>     buf 显示的是第一个字符 strcpy(pNumber,strNumber);      ==>    e ...

  2. Do not use the <section> element as a generic container; this is what <div> is for, especially when the sectioning is only for styling purposes.

    Do not use the <section> element as a generic container; this is what <div> is for, espe ...

  3. Java,多个线程对同一个数据源的访问

    当多个线程对同一个数据源进行访问时,应对线程同步或加锁.为何?举个简单的例子:有一个共享的数据源dataSource,其值为0.有两个线程,Thread1和Thread2.Thread1的任务是将da ...

  4. idea 破解注册方法总结

    注册码(无期限) JetbrainsCrack-2.6.2.jar适用于ideaIU-2017.2.之前版本,若版本较新适用 JetbrainsCrack-2.6.3_proc.jar. 其中Jetb ...

  5. POJ1426 Find The Multiple —— BFS

    题目链接:http://poj.org/problem?id=1426 Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Tota ...

  6. 调节音量的各个方法——AudioManager的使用

    AudioManager类位于android.Media包中,该类提供访问控制音量和铃声模式的操作. //获取AudioManager实例对象 AudioManager audioManage = ( ...

  7. jquery实现无限滚动瀑布流实现原理

    现在类似于pinterest这类的表现效果很火,其实我比较中意的是他的布局效果,而不是那种瀑布流. 虽然我不是特别喜欢这种瀑布流的表现样式,但是还是写了几篇关于无限滚动瀑布流效果的文章,Infinit ...

  8. 【POJ 2406】 Power Strings

    [题目链接] 点击打开链接 [算法] KMP 如果字符串中存在循环节,则next[len] = (循环节个数 - 1) * 循环节长度 循环节个数 = len / (len - next[len]) ...

  9. AutoIt: send 命令 VS ControlClick的使用

    2008年的时候第一次接触AutoIt,当时觉得局限性太多了,就不想学,觉得把Watir,Ruby搞好就行了. 最近一段时间比较闲,发现自己对GUI的自动化操完全是短板,就把AutoIt重新拾起来了. ...

  10. Code-NFine:下来框和复选框

    ylbtech-Code-NFine:下来框和复选框 1.返回顶部 1. 1.1 html $("#F_OrganizeId").bindSelect({ url: "/ ...