双缓冲画图,它是一种主要的图形图像画图技术。首先,它在内存中创建一个与屏幕画图区域一致的对象,然后将图形绘制到内存中的这个对象上,最后把这个对象上的图形数据一次性地拷贝并显示到屏幕上。

这样的技术能够大大地提高画图的速度,降低卡顿和闪屏的问题。

Tip:

去看看吧。1.

我们为什么要使用双缓冲技术来进行画图?

    在应用程序开发中,当图像信息数据量非常大时。画图可能须要几秒钟甚至更长的时间,这时。应用程序可能会出现卡顿的现象。另外,假设窗体在响应WM_PAINT消息的同一时候也要进行复杂的图形处理。那么窗体在重绘时就会由于频繁的刷新而引起闪烁现象。而使用双缓冲技术就能有效地解决以上问题。

闪烁问题:

    窗体在刷新时,总要有一个擦除原来图象的过程OnEraseBkgnd,它利用背景色填充窗体画图区,然后再调用新的画图代码进行重绘。这样一擦一写造成了图象颜色的反差。当WM_PAINT的响应非常频繁的时候,这样的反差也就越发明显。

于是我们就看到了闪烁现象。

假设仅仅是仅仅去掉背景色的填充。的确不管如何重画图形都不会闪了。可是那样的话,窗体画面往往会变的乱七八糟。由于每次绘制图象的时候都没有将原来的图象清除,造成了图象的残留。叠加了新图形。

所以单纯的禁止背景重绘是不够的,我们还要进行又一次画图。

画图函数可使用 BitBlt。它支持图形块的复制。速度非常快。

双缓冲画图实现方式:

    首先把要显示的图形先在内存中绘制好。然后再一次性地将内存中的图形一个点一个点地覆盖到屏幕上去(这个过程非常快,由于是非常完整的内存拷贝),以至于用背景色擦除界面后再贴图到屏幕上也不会闪烁了。

    步骤:

  1. 在内存中创建与画布一致的缓冲区;
  2. 在缓冲区画图;
  3. 将缓冲区位图复制到当前画布并显示到屏幕上;
  4. 释放内存缓冲区。

流程图:

代码实现:

    这里在VC++开发平台使用MFC开发,一般在OnDraw和OnPaint函数中进行图像绘制。

    首先屏蔽背景刷新,背景刷新事实上是在响应WM_ERASEBKGND消息。我们仅仅要把OnEraseBkgnd函数返回值改为TRUE即可了。

//`直接画图`,这里重绘会出现卡顿现象
void CDoubleBufferDlg::DrawItem(CDC* pDC)
{
ASSERT_VALID(pDC); CRect rcClient;
pDC->GetClipBox(rcClient); CPen pen(PS_SOLID, 1, RGB(178,178,178));
CPen* pOldPen = NULL; pOldPen = pDC->SelectObject(&pen); pDC->Ellipse(rcClient); for(int j=0;j<1000;j++)
{
pDC->MoveTo(0,0);
pDC->LineTo(rcClient.Width(),rcClient.Height()); pDC->MoveTo(rcClient.Width(),0);
pDC->LineTo(0,rcClient.Height());
} //画图完毕后的清理
pDC->SelectObject(pOldPen);
pOldPen->DeleteObject();
}
//`双缓冲画图`
void CDoubleBufferDlg::DrawItemWithDoubleBuffer(CDC* pDC)
{
ASSERT_VALID(pDC); CRect rcClient;
pDC->GetClipBox(rcClient); // 定义一个内存显示设备上下文对象
CDC MemDC; // 定义一个GDI位图对象
CBitmap MemBitmap; // 创建一个与指定设备(这里是屏幕)兼容的内存设备上下文环境(DC)
MemDC.CreateCompatibleDC(pDC); // 建立一个与屏幕显示兼容的位图,位图的大小可选用窗体客户区的大小
MemBitmap.CreateCompatibleBitmap(pDC, rcClient.Width(), rcClient.Height()); // 将位图对象选入到内存显示设备上下文中。仅仅有选择了才干进行画图
CBitmap *pOldBit = MemDC.SelectObject(&MemBitmap); // 先用白色背景色将位图清除干净,否则是黑色。
MemDC.FillSolidRect(0, 0, rcClient.Width(), rcClient.Height(), RGB(255,255,255)); // 定义画笔。颜色为灰色
CPen pen(PS_SOLID, 1, RGB(178,178,178));
CPen* pOldPen = NULL; // 把画笔对象选定到指定的设备上下文环境中
pOldPen = MemDC.SelectObject(&pen); //-----------------------------------------画图操作
// 需放在BitBlt函数前 // 画椭圆
MemDC.Ellipse(rcClient); // 画对角线,循环次数多,没有双缓冲会卡顿
for(int i=0;i<1000;i++)
{
MemDC.MoveTo(0,0);
MemDC.LineTo(rcClient.Width(), rcClient.Height()); MemDC.MoveTo(rcClient.Width(), 0);
MemDC.LineTo(0, rcClient.Height());
}
//-----------------------------------------画图操作 // 将内存中的图复制到屏幕上进行显示
pDC->BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &MemDC, 0, 0, SRCCOPY); // 画图完毕后的清理
MemDC.SelectObject(pOldPen);
MemDC.SelectObject(pOldBit); //使用GetDC()要用ReleaseDC
::ReleaseDC(this->m_hWnd, MemDC);
pOldPen->DeleteObject();
MemBitmap.DeleteObject();
}

效果图:

知识概念(摘自百度百科):

GDI

    在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函数就能够方便的在屏幕、打印机及其他输出设备上输出图形,文本等操作。那我们GDI究竟是什么呢?

    GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与画图程序之间的信息交换,处理全部Windows程序的图形输出。它的出现使程序猿无须要关心硬件设备及设备驱动。就能够将应用程序的输出转化为硬件设备上的输出,实现了程序开发人员与硬件设备的隔离,大慷慨便了开发工作。GDI有下面几个特点:

  1. 不同意程序直接訪问物理显示硬件。通过称为“设备环境(DC)”的抽象接口间接訪问显示硬件。
  2. 程序须要与显示硬件(显示器、打印机等) 进行通讯时,必须首先获得与特定窗体相关联的设备环境。
  3. 用户无需关心详细的物理设备类型。
  4. Windows參考设备环境的数据结构完毕数据的输出。

以上的设备环境,就是我们的DC(device context)。

DC(device context)

    在Windows环境中,各程序的输出必须限制在自己的窗体中。

GDI用一种简单的机制保证在窗体中画图的各程序遵循这个规则。

这样的机制即为设备描写叙述表(DC);当Windows程序在屏幕、打印机或其他设备上画图时,它并非将像素直接输出到设备上,而是将图绘制到由设备描写叙述表表示的逻辑意义上的”显示平面”上去。设备描写叙述表是深寓于Windows中的一种数据结构,它包含GDI须要的全部关于显示平面情况的描写叙述字段。包含相连的物理设备和各种各样的状态信息。

    设备描写叙述表,又称为设备上下文。或者设备环境,它是一个定义一组图形对象(画笔等等)及其属性、影响输出的图形方式(数据)结构。windows提供设备描写叙述表。用于应用程序和物理设备之间进行交互,从而提供了应用程序设计的平台无关性。

    设备描写叙述表是一种数据结构,它包含了一个设备(如显示器和打印机)的绘制属性相关的信息。全部的绘制操作通过设备描写叙述表进行。设备描写叙述表与大多 WIN32结构不同,应用程序不能直接訪问设备描写叙述表,仅仅能由各种相关API函数通过设备描写叙述表的句柄间接訪问该结构。

    设备描写叙述表总是与某种系统硬件设备相关。

比方屏幕设备描写叙述表与显示设备相关。打印机设备描写叙述表与打印设备相关等等。

屏幕设备描写叙述表。一般我们简单地称其为设备描写叙述表。它与显示设备具有一定的相应关系。在windows GDI界面下。它总是相关于某个窗体或这窗体上的某个显示区域。

通常意义上窗体的设备描写叙述表。一般指的是窗体的客户区,不包含标题栏、菜单条所占有的区域,而对于整个窗体来说,其设备描写叙述表严格意义上来讲应该称为窗体设备描写叙述表。它包含窗体的全部显示区域。二者的操作方法全然一致,所不同的仅仅是可操作的范围不同而已。

    windows 窗体一旦创建,它就自己主动地产生了与之相相应的设备描写叙述表数据结构,用户可运用该结构。实现对窗体显示区域的GDI操作,如划线、写文本、绘制位图、填充等。而且全部这些操作均要通过设备描写叙述表句柄来进行。


  1. 这是第一次用 Markdown博客,故借用脚注纪念一下吧。哈哈!

VC双缓冲画图技术介绍的更多相关文章

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

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

  2. C#-gdi画图,双缓冲画图,Paint事件的触发---ShinePans

    在使用gdi技术画图时,有时会发现图形线条不够流畅,或者在改变窗口大小时会闪烁不断的现象.(Use DoubleBuffer to solve it!)                         ...

  3. c# GDI画图 双缓冲画图分析

    双缓冲绘图分析  1.Windows 绘图原理  我们在 Windows 环境下看到各种元素,如菜单.按钮.窗口.图像,从根本上说,都是“画”出来的.这时的屏幕,就相当于一块黑板,而 Windows ...

  4. [转载] MFC绘制动态曲线,用双缓冲绘图技术防闪烁

    转载的原文地址 先上效果图 随着时间的推移,曲线向右平移,同时X轴的时间坐标跟着更新. 一.如何绘制动态曲线 所谓动画,都是一帧一帧的图像连续呈现在用户面前形成的.所以如果你掌握了如何绘制静态曲线,那 ...

  5. win32下的双缓冲绘图技术

    一:双缓冲原理 为了解决窗口刷新频率过快所带来的闪烁问题,利用双缓冲技术进行绘图.所谓双缓冲技术,就是将资源加载到内存,然后复制内存数据到设备DC(这个比较快),避免了直接在设备DC上绘图(这个比较慢 ...

  6. VC++双缓冲保持背景不擦除之实现

    几天前,我终于克服了C++窗体重绘时的闪烁问题,用到的技巧就是双缓冲.但是怎样保持住已经绘制的图形呢?也就是仿照Windows自带的画图程序一般,动态的做出一条直线.最容易想到的方法是在MouseMo ...

  7. [Android学习笔记]双缓冲绘图技术

    双缓冲技术绘图: 什么情况下产生的双缓冲技术?当数据量很大时,绘图可能需要花费很长的时间,这样屏幕就会出现卡顿,闪烁等现象. 什么是双缓冲技术?双缓冲是在内存中创建一个与屏幕绘制区域一致的对象,先将图 ...

  8. Win32下双缓冲绘图技术

    一:双缓冲原理 为了解决窗口刷新频率过快所带来的闪烁问题,利用双缓冲技术进行绘图.所谓双缓冲技术,就是将资源加载到内存,然后复制内存数据到设备DC(这个比较快),避免了直接在设备DC上绘图(这个比较慢 ...

  9. MFC VC 双缓冲绘图基本原理与实现,详细解释

    转自:http://blog.csdn.net/foreverhuylee/article/details/21548107 当然你可以直接搜索到能用的代码,并且基本能满足要求.不过这样总不是学习的态 ...

随机推荐

  1. 服务器搭建域控与SQL Server的AlwaysOn环境过程(三)配置故障转移

    0 引言 主要讲述如何搭建故障转移集群,因为AlwaysOn是基于Windows的故障转移集群的. 在讲解步骤之前需要了解一下故障转移集群仲裁配置 下面图片来自<Windows Server20 ...

  2. css 禁止文本被选中复制代码

    css 禁止文本被选中复制代码: .cus-text{ -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none ...

  3. syn攻击原理与防护措施

    何为syn攻击? 先普及下tcp3次握手的知识,在TCP/IP中,tcp协议提供可靠的socket连接服务,通过3次握手建立可靠连接. tcp3次握手过程: 第一阶段:某终端向服务器发送syn(syn ...

  4. 紫书 习题 8-1 UVa 1149(贪心)

    排序之后, 尽量最小和最大的放在一个背包, 放不下就放最大的. #include<cstdio> #include<algorithm> #define REP(i, a, b ...

  5. 魔兽争霸RPG游戏-军团战争-游戏经验总结

    终于要写这篇了,上一篇是个意外. 2015年关注,一代鬼王Xun和GGL比赛.晚上11点之后,经常有水友赛.主播xun,会带着一帮小弟,玩一些游戏.比如魔兽争霸6v6,2v2,RPG游戏-军团战争,疯 ...

  6. hadoop-07-ntp服务检查

    hadoop-07-ntp服务检查 cd /etc/more /etc/ntp.conf里面进行了server的配置 service ntpd status / stop/ start 安装ntpd ...

  7. HDU--4891--The Great Pan--暴力搜索

    The Great Pan Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) To ...

  8. LightOJ - 1132 Summing up Powers 矩阵高速幂

    题目大意:求(1^K + 2^K + 3K + - + N^K) % 2^32 解题思路: 借用别人的图 能够先打表,求出Cnm,用杨辉三角能够高速得到 #include<cstdio> ...

  9. 设计模式-策略模式(Go语言描写叙述)

    好久没有更新博客了.近期也是在忙着充电,今天这篇博客開始,我们来了解一下设计模式. 设计模式 那什么是设计模式呢?首先来看看我从百科上copy下来的概念吧. 设计模式/软件设计模式(Design pa ...

  10. thinkphp5的Illegal string offset 'id'错误

    thinkphp5的Illegal string offset 'id'错误 问题 解答 数组同名了,一个html页面传进来两个cateres的数组,所以在找id的时候不知道找这两个里面的哪一个 第一 ...