一、简介

在进行复杂图形绘制时,若直接在屏幕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. struct与 union的基本用法

    结构体与联合体是C语言的常见数据类型,可对C的基本数据类型进行组合使之能表示复杂的数据结构,意义深远,是优异代码的必备工具.一.        struct与 union的基本用法,在语法上union ...

  2. java序员必备的十大技能

    想成为一名出色的Java程序员么?本文将为大家重点介绍程序员必备的十大技能,成就您的梦想.       1.语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样 ...

  3. C++11 std::function、std::bind和lambda表达式

    参考博客: C++可调用对象详解-https://www.cnblogs.com/Philip-Tell-Truth/p/5814213.html 一.关于std::function与std::bin ...

  4. Mysql的Merge存储引擎实现分表查询

    对于数据量很大的一张表,i/o效率底下,分表势在必行! 使用程序分,对不同的查询,分配到不同的子表中,是个解决方案,但要改代码,对查询不透明. 好在mysql 有两个解决方案: Partition(分 ...

  5. Spring Boot 整合Servlet

    冷知识,几乎用不到 在spring boot中使用Servlet有两种实现方法: 方法一: 正常创建servlet,然后只用注解@ServletComponentScan package clc.us ...

  6. sjtu oj 1201. SuperXOR

    Description Pangzi recently realized that bitwise XOR operation is just an addition without carries. ...

  7. get all sites under IIS

    https://stackoverflow.com/questions/2555668/how-to-programmatically-get-sites-list-and-virtual-dirs- ...

  8. vue中使用axios post上传头像/图片并实时显示到页面

    在前端开发中,为了更好的用户体验,在头像上传时会先将图片显示到页面然后点击保存按钮 完成图片的上传成功 代码部分有参考他人的写法. html代码:   <div id="myPhoto ...

  9. springboot web项目搭建

    1.选择spring initializr 2.填写应用名称及设置相关配置,建议使用默认配置即可 3.选择相关技术,我们现在web技术 4.填写项目名称 5.项目文件结构如下 6.直接运行 java ...

  10. 书写优雅的shell脚本(插曲)- ed编辑器

    今天发现了一个灰常好用的unix/linux文本行编辑器:ed,对于进行面向行的文本编辑工作她真是太棒了,比vi操作简单.方便.功能强大.感兴趣的同仁可以尝试一下!