VC++绘图时,利用双缓冲解决屏幕闪烁 转载
最近做中国象棋,绘制界面时遇到些问题,绘图过程中屏幕闪烁,估计都会想到利用双缓冲来解决问题,但查了下网上双缓冲的资料,发现基本是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++绘图时,利用双缓冲解决屏幕闪烁 转载的更多相关文章
- VC 绘图,使用双缓冲技术实现
VC 绘图,使用双缓冲技术实现 - Cloud-Datacenter-Renewable Energy-Big Data-Model - 博客频道 - CSDN.NET VC 绘图,使用双缓冲技术实现 ...
- Android 绘图时实现双缓冲
一.双缓冲技术原理: 在内存中创建一片内存区域,把将要绘制的图片预先绘制到内存中,在绘制显示的时候直接获取缓冲区的图片进行绘制.更具体一点来说:先通过setBitmap方法将要绘制的所有的图形绘制到一 ...
- MFC双缓冲解决图象闪烁[转]
转载网上找到的一篇双缓冲的文章,很好用.http://www.cnblogs.com/piggger/archive/2009/05/02/1447917.html__________________ ...
- C#中利用双缓冲技术解决绘图闪屏问题。
这段时间在做一个小型游戏,在界面显示的时候用到了一些图形.一开始涉及到的图形全都用控件的背景图片代替了.这样游戏运行的时候存在的一个很大的问题是游戏运行很慢.小组成员费尽周折,即将放弃,每一个成员都愁 ...
- 双缓冲解决控制台应用程序输出“闪屏”(C/C++,Windows)
使用 C 语言编写游戏的小伙伴们想必起初都要遇到这样的问题,在不断清屏输出数据的过程中,控制台中的输出内容会不断地闪屏.出现这个问题的原因是程序对数据处理花掉的时间影响到了数据显示,或许你可以使用局部 ...
- 【MFC】利用双缓冲和随机函数rand()实现蒲公英飞舞
原始日期:2014-05-29 22:44 这几天有些懒,几乎没怎么学MFC了,好容易有个题目:用双缓冲实现蒲公英飞舞,想来想去也没想到好方法,索性动手开始 写了 ,这一写,得,出来了,呵呵,无意中产 ...
- Java中用双缓冲技术消除闪烁
在Java编写具有连贯变化的窗口程序时,通常的办法是在子类中覆盖父类的paint(Graphics)方法,在方法中使用GUI函数实现窗口重绘的过程.连贯变换的窗口会不断地调用update(Graphi ...
- HTML5_canvas_图片加载_双缓冲_跳帧闪烁问题
canvas 图片加载 pen.drawImage(ele, showX, showY, imgWidth, imgHeight); ele 将 img 元素 加载到画布上 步骤 1. 创建一个 ...
- Delphi 使用双缓冲解决图片切换时的闪烁问题 good
var TempCanvas: TCanvas; BufDC: HDC; BufBitmap: HBITMAP; begin // 创建一个与显示设备兼容的内存设备 BufDC := CreateCo ...
随机推荐
- cocos2d 保存最近登陆多个账号最多一个月
用的是一个单例来管理 ,数据是存在本地的xml文件里的格式如下 <?xml version="1.0" encoding = "utf-8" ?> ...
- map的应用
1.map最基本的构造函数: map<string , int >mapstring; map<int ,string >mapint; map&l ...
- ADC 电源监测
我能为别人做点什么?这是我最近在思考的问题. 看了 ADC 电源监测代码,觉得对 ADC 的理解不到位,代码中有很多部分都不懂.如: 1. 为什么初始化的时候管脚设置为输出? 2. ADC 采集到的值 ...
- FineUI中Newtonsoft.Json版本报错解决办法
1.清空bin下的Newtonsoft.Json.dll 2.使用Nuget安装最新版本的Newtonsoft.Json.dll,安装脚本为 Install-Package Newtonsoft.Js ...
- 转 https://www.zhihu.com/question/27606493/answer/37447829
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:梁川链接:https://www.zhihu.com/question/27606493/answer/37447829来源: ...
- Jquery tab 选项卡 无刷新切换
转载的 演示地址:http://www.freejs.net/demo/29/index.html 首页>>TAB标签>>jquery实现简单的Tab切换菜单(2013-09- ...
- C++多重继承带来的问题
首先上图,咱们看图说话! 橙色表示变量,使用private修饰. 如图,假设Person类的变量name只能通过input方法来输入. 那么继承自Person的Student及Teacher类中s ...
- Linux命令全集
一.Ubuntu10.4 启动纯文件界面 打开 /etc/default/grub 文件, 注释掉 GRUB_CMDLINE_LINUX_DEFAULT="quiet splash&quo ...
- docker中使用systemd
由于以下几个原因,docker的官方centos镜像中没有提供systemd服务: systemd requires the CAP_SYS_ADMIN capability. This mean ...
- linux 下 用户与用户组
1,增加一个test组:groupadd test 2,将test组重命名test2:groupmod -n test2 test 3,删除test2组:groupdel test2 4,查看当前登录 ...