一、简介

在进行复杂图形绘制时,若直接在屏幕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. C系列语言终极校对宝典【第一、第二部分】

    第一部分:基本概念及其它问答题 1.关键字static的作用是什么? 这个简单的问题很少有人能回答完全.在C语言中,关键字static有三个明显的作用: 1). 在函数体,一个被声明为静态的变量在这一 ...

  2. 深入解析Hibernate核心接口

    Hibernate有很多值得学习的地方,这里我们主要介绍Hibernate核心接口,包括介绍SessionFactory接口.Query和Criteria接口等方面. Session 接口对于Hibe ...

  3. 编写自定义PE结构的程序(如何手写一个PE,高级编译器都是编译好的PE头部,例如MASM,TASM等,NASM,FASM是低级编译器.可以自定义结构)

    正在学PE结构...感谢个位大哥的文章和资料...这里先说声谢谢 一般高级编译器都是编译好的PE头部,例如MASM,TASM等一直都说NASM,FASM是低级编译器.可以自定义结构但是苦于无人发布相关 ...

  4. css简单的数学运算

    calc()是css3的一个新增的属性, .box{border:1px solid #ddd;  width:calc(100% - 100px);  background:#9AC8EB;} 兼容 ...

  5. (linux)likely和unlikely函数

      在Linux内核中likely和unlikely函数有两种(只能两者选一)实现方式,它们的实现原理稍有不同,但作用是相同的,下面将结合linux-2.6.38.8版本的内核代码来进行讲解. 1.对 ...

  6. poj 1724 ROADS 解题报告

    题目链接:http://poj.org/problem?id=1724 题目意思:给出一个含有N个点(编号从1~N).R条边的有向图.Bob 有 K 那么多的金钱,需要找一条从顶点1到顶点N的路径(每 ...

  7. oracle:os认证用户登录测试

        90%的情况下,我们使用的都是数据库认证用户登录oracle,但还存在使用OS认证用户登录oracle的情况: 下面就实验一下OS用户要登录oracle相关操作: 测试环境:oracle10. ...

  8. 1Q84 BOOK 1-3 笔记

    1Q84 BOOK 1-3 村上春树 18个笔记     ◆ 第2章 青豆 不要被外表迷惑   >> 在这三十年的人生中,究竟听过多少次同样的台词?为了这个姓氏,曾经多少次遭人调侃?如果不 ...

  9. JQuery判断div(控件)是否为隐藏

    以下是JavaScript 中判断div是否为隐藏代码引用片段: if (div.style.display == "none") { div.style.display = &q ...

  10. [SoapUI] Jenkins 配置不同环境(TP, LIVE)