最近做中国象棋,绘制界面时遇到些问题,绘图过程中屏幕闪烁,估计都会想到利用双缓冲来解决问题,但查了下网上双缓冲的资料,发现基本是MFC的,转化为VC++后,大概代码如下:

void DrawBmp(HDC hDC, HBITMAP hBitmap)
{
HDC hdcMEM; //用于缓冲作图的内存DC
HBITMAP bmp; //内存中承载临时图象的位图
HANDLE hOld;
hdcMEM = CreateCompatibleDC(hDC);//依附窗口DC创建兼容内存DC
bmp = CreateCompatibleBitmap(hDC, , ); //创建与hDC环境相关的设备兼容的位图 SelectObject(hdcMEM, bmp);
hOld = SelectObject(hdcImage, hBitmap); StretchBlt(hDC, , , , , hdcMEM, , , , , SRCCOPY); SelectObject(hdcImage, hOld);
DeleteObject(hOld);
}

但以上代码似乎没有用到hBitmap,当然屏幕上也不会有任何输出,但网上的资料基本一样。查了一番资料,才明白如果hDC中已经有位图数据,BitBlt的时候,就会直接把hDC中的数据画到内存缓冲区里。所以,还需要建一DC,名为hdcImage,把要画的位图选入内存hdcImage中,然后再在内存缓冲区上绘图。

整理代码如下:

void DrawBmp(HDC hDC, HBITMAP hBitmap)
{
HDC hdcImage;
HDC hdcMEM; //注意此处,创建了两个HDC
hdcMEM = CreateCompatibleDC(hDC);
hdcImage = CreateCompatibleDC(hDC);
HBITMAP bmp = ::CreateCompatibleBitmap(hDC, nWidth, nHeight);//创建与hDC环境相关的设备兼容的位图 SelectObject(hdcMEM, bmp); SelectObject(hdcImage, hBitmap);//注意此处,将要画的位图选入hdcImage StretchBlt(hdcMEM, , , , , hdcImage, , , , , SRCCOPY); //这里才能正常画图,将hdcImage中的位图直接复制到内存缓冲区
StretchBlt(hDC, , , , , hdcMEM, , , , , SRCCOPY); //再将内存缓冲区中的数据绘制到屏幕上. DeleteObject(hdcImage); }

当然,要注意的一点就是,如果要绘制多张图片,比如两张,如果大家这样调用:
DrawBmp(hDC, hBitmap1);
DrawBmp(hDC, hBitmap2);
依然会发生闪烁,下面解释原因:
举个例子,屏幕绘图就像现场作画,如果两次调用绘图函数,就相当于在观众面前作画,第一次画第一张(例如中国象棋的背景)。第二次画第二张(如棋盘)。这样,在画背景和棋盘时,由于颜色有反差,必然在贴第二张图时会发现闪烁,这样利用双缓冲相当于没用,还浪费了内存空间。

双缓冲的原理是:在内存中先把第一张图画好,此时不要转画到屏幕上,然后继续在原来的内存中画第二张,等把所有的图全画好后,再一次性贴到屏幕上。那样内存中存在的就是完整的图形,观众看不到绘图的过程,只能看到绘图的结果,而最后是一次性复制到屏幕上的,当然不会发生闪烁现象。

为了更好解释双缓冲的原理,附图片如下:

PS:以上照片来自网络,只为能更好理解,本人无意侵权。

在以上代码的基础上作如下更改:

void DrawBmp(HDC hDC, HBITMAP hBitmap) //此处返回类型改为HDC
{
HDC hdcMEM;
hdcMEM = CreateCompatibleDC(hDC); SelectObject(hdcMEM, hBitmap); //将位图选择进内存DC StretchBlt(hDC, , , , , hdcMEM, , , , , SRCCOPY);//这里才能正常画图,将hdcImage中的位图直接复制到内存缓冲区 DeleteObject(hdcMEM);
}

调用以上函数在内存中画第一张图:
DrawBmp(hdcTmp , hBitmap1);
画第二张图
DrawBmp(hdcTmp, hBitmap2); //此时传的为hdcTmp,其中hdcTmp中已经有第一张图片的数据,此次调用后就会把第二张图片绘到原来的基础上。

如果要画多张图,就依次调用本函数绘制,记得一定要把所有的图全画到一个设备DC上,最后再一次性画到屏幕上,才不会出现闪烁现象。
等把所有图全画到hdcTmp中后,hdcTmp中已经有了完整的图形,再把完整的图形绘制到屏幕上:
BitBlt(hDC, 0, 0, 100, 100, hdcTmp, 0, 0, SRCCOPY); //此处第一个参数才为hDC,即窗口句柄

至此,双缓冲画多幅图绘制完毕。

VC++绘图时,利用双缓冲解决屏幕闪烁 转载的更多相关文章

  1. VC 绘图,使用双缓冲技术实现

    VC 绘图,使用双缓冲技术实现 - Cloud-Datacenter-Renewable Energy-Big Data-Model - 博客频道 - CSDN.NET VC 绘图,使用双缓冲技术实现 ...

  2. Android 绘图时实现双缓冲

    一.双缓冲技术原理: 在内存中创建一片内存区域,把将要绘制的图片预先绘制到内存中,在绘制显示的时候直接获取缓冲区的图片进行绘制.更具体一点来说:先通过setBitmap方法将要绘制的所有的图形绘制到一 ...

  3. MFC双缓冲解决图象闪烁[转]

    转载网上找到的一篇双缓冲的文章,很好用.http://www.cnblogs.com/piggger/archive/2009/05/02/1447917.html__________________ ...

  4. C#中利用双缓冲技术解决绘图闪屏问题。

    这段时间在做一个小型游戏,在界面显示的时候用到了一些图形.一开始涉及到的图形全都用控件的背景图片代替了.这样游戏运行的时候存在的一个很大的问题是游戏运行很慢.小组成员费尽周折,即将放弃,每一个成员都愁 ...

  5. 双缓冲解决控制台应用程序输出“闪屏”(C/C++,Windows)

    使用 C 语言编写游戏的小伙伴们想必起初都要遇到这样的问题,在不断清屏输出数据的过程中,控制台中的输出内容会不断地闪屏.出现这个问题的原因是程序对数据处理花掉的时间影响到了数据显示,或许你可以使用局部 ...

  6. 【MFC】利用双缓冲和随机函数rand()实现蒲公英飞舞

    原始日期:2014-05-29 22:44 这几天有些懒,几乎没怎么学MFC了,好容易有个题目:用双缓冲实现蒲公英飞舞,想来想去也没想到好方法,索性动手开始 写了 ,这一写,得,出来了,呵呵,无意中产 ...

  7. Java中用双缓冲技术消除闪烁

    在Java编写具有连贯变化的窗口程序时,通常的办法是在子类中覆盖父类的paint(Graphics)方法,在方法中使用GUI函数实现窗口重绘的过程.连贯变换的窗口会不断地调用update(Graphi ...

  8. HTML5_canvas_图片加载_双缓冲_跳帧闪烁问题

    canvas 图片加载 pen.drawImage(ele, showX, showY, imgWidth, imgHeight); ele    将 img 元素 加载到画布上 步骤 1. 创建一个 ...

  9. Delphi 使用双缓冲解决图片切换时的闪烁问题 good

    var TempCanvas: TCanvas; BufDC: HDC; BufBitmap: HBITMAP; begin // 创建一个与显示设备兼容的内存设备 BufDC := CreateCo ...

随机推荐

  1. Jena TDB 102

    1 Introduction TDB is a RDF storage of Jena. official guarantees and limitations TDB support full ra ...

  2. 当pip install不能正确安装的时候,try easy_install

    当pip install不能正确安装的时候,try easy_install 重复试了几次pip install -r requirements.txt,都在安装pillow的时候失败了,想找这个枕头 ...

  3. R中的统计检验函数

    正态性W检验 shapiro.test()用Shapiro-Wilk W统计量做数据的正态性检验. 经验分布的Kolmogorov-Smirnov检验 ks.test()Kolmogorov-Smir ...

  4. java实现定时任务的三种方法

    /** * 普通thread * 这是最常见的,创建一个thread,然后让它在while循环里一直运行着, * 通过sleep方法来达到定时任务的效果.这样可以快速简单的实现,代码如下: * @au ...

  5. 39:第n小的质数

    39:第n小的质数    总时间限制:    1000ms    内存限制:    65536kB描述    输入一个正整数n,求第n小的质数.输入    一个不超过10000的正整数n.输出    ...

  6. Maven学习 (一) 搭建Maven环境

      有两种方式可以配置maven的环境配置,本人推荐使用第二种,即使用本地的maven安装文件,个人感觉这样可以方便管理下载jar包的存放位置,错误信息的输出等,可以在dos窗口中可以清晰看到,虽然比 ...

  7. PC安装了MAC,那么CMD键和OPTION键什么的在哪里?

    OS X中Command键所在的位置对应windows中Alt键的位置,OS X中Option键对应windows中Shift键的位置.如果使用中有不习惯的地方,可以通过设置修改,具体方法如下: 1. ...

  8. JS获取当前日期时间及JS日期格式化

    Js获取当前日期时间: var myDate = new Date(); myDate.getYear(); //获取当前年份(2位) myDate.getFullYear(); //获取完整的年份( ...

  9. nokogiri如何使用

    直接来个简单的代码实例就明白啦! require 'nokogiri' xml_data=<<XML <library> <NAME><![CDATA[Fav ...

  10. flex loaderInfo为null在creationComplete事件中

    原文: http://yunzhongxia.iteye.com/blog/1152670   Flex4中application变为FlexGlobals.topLevelApplication,很 ...