1.显示的图形为什么会闪烁

我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的,其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。例如在OnDraw(CDC *pDC)中这样写:

pDC->MoveTo(0,0);

pDC->LineTo(100,100);

这个绘图过程应该是非常简单、非常快了吧,但是拉动窗口变化时还是会看见闪烁。其实从道理上讲,画图的过程越复杂越慢闪烁应该越少,因为绘图用的时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。比如:清楚屏幕时间为1s绘图时间也是为1s,这样在10s内的连续重画中就要闪烁5次;如果清楚屏幕时间为1s不变,而绘图时间为9s,这样10s内的连续重画只会闪烁一次。这个也可以试验,在OnDraw(CDC *pDC)中这样写:

for(int i=0;i<100000;i++)

{

pDC->MoveTo(0,i);

pDC->LineTo(1000,i);

}

程序有点极端,但是能说明问题。

说到这里可能又有人要说了,为什么一个简单图形看起来没有复杂图形那么闪呢?这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要闪得厉害一些,但是闪烁频率要低。那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了,闪烁是什么?闪烁就是反差,反差越大,闪烁越厉害。因为动画的连续两个帧之间的差异很小所以看起来不闪。如果不信,可以在动画的每一帧中间加一张纯白的帧,不闪才怪呢。

2、如何避免闪烁

在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉MFC提供的背景绘制过程了。实现的方法很多:

* 可以在窗口形成时给窗口的注册类的背景刷付NULL

* 也可以在形成以后修改背景

static CBrush brush(RGB(255,0,0));

SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);

* 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE

这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,变得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。

3、如何实现双缓冲

首先给出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中:

CDC MemDC; //首先定义一个显示设备对象

CBitmap MemBitmap;//定义一个位图对象//随后建立与屏幕显示兼容的内存显示设备

MemDC.CreateCompatibleDC(NULL);//这时还不能绘图,因为没有地方画//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小

MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);//将位图选入到内存显示设备中//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上

CBitmap*pOldBit=MemDC.SelectObject(&MemBitmap);//先用背景色将位图清除干净,这里我用的是白色作为背景//你也可以用自己应该用的颜色

MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));//绘图

MemDC.MoveTo(……);

MemDC.LineTo(……);//将内存中的图拷贝到屏幕上进行显示

pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);//绘图完成后的清理

MemBitmap.DeleteObject();

MemDC.DeleteDC();

请参阅注释。

4、如何提高绘图的效率

实际上,在OnDraw(CDC *pDC)中绘制的图并不是所有都显示了的,例如:你在OnDraw中画了两个矩形,在一次重绘中虽然两个矩形的绘制函数都有执行,但是很有可能只有一个显示了,这是因为MFC本身为了提高重绘的效率设置了裁剪区。裁剪区的作用就是:只有在这个区内的绘图过程才会真正有效,在区外的是无效的,即使在区外执行了绘图函数也是不会显示的。因为多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生,改变的区域并不是整个图形而只有一小部分,这一部分需要改变的就是pDC中的裁剪区了。因为显示(往内存或者显存都叫显示)比绘图过程的计算要费时得多,有了裁剪区后显示的就只是应该显示的部分,大大提高了显示效率。但是这个裁剪区是MFC设置的,它已经为我们提高了显示效率,在进行复杂图形的绘制时如何进一步提高效率呢?那就只有去掉在裁剪区外的绘图过程了。可以先用pDC->GetClipBox()得到裁剪区,然后在绘图时判断你的图形是否在这个区内,如果在就画,不在就不画。

如果你的绘图过程不复杂,这样做可能对你的绘图效率不会有提高。

具体程序大家可看以下源代码:

5、无闪烁背景图的绘制代码实现

/**无闪烁背景图绘制//

BOOL CStrucView::OnEraseBkgnd(CDC*pDC)

{intnWidth;intnHeight;//CView::OnEraseBkgnd(pDC);

CStrucDoc* pDoc =GetDocument();

ASSERT_VALID(pDoc);

CRect rect;

GetWindowRect(&rect);

nWidth=rect.Width();

nHeight=rect.Height();

CDC MemDC;

CBitmap MemBitmap;

MemDC.CreateCompatibleDC (NULL);

MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);

CBitmap*pOldBit=MemDC.SelectObject(&MemBitmap);

MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));/** 以上为画背景色// 以下为画背景图/

GetClientRect(rect);

BITMAP bm;

CDC dcMem;

VERIFY(m_bmp.GetObject(sizeof(bm),(LPVOID)&bm));

dcMem.CreateCompatibleDC(pDC);

CBitmap*pOldBMP =( CBitmap *)dcMem.SelectObject(&m_bmp);

MemDC.BitBlt( (rect.right- bm.bmWidth)/2,

(rect.bottom- bm.bmHeight)/2,

bm.bmWidth,bm.bmHeight,&dcMem,0,0,SRCCOPY);

dcMem.SelectObject(pOldBMP);/** 以上为画背景图/pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);

MemBitmap.DeleteObject();

MemDC.DeleteDC();returnTRUE;

}/**无闪烁背景图绘制/注:程序中m_bmp 为相应 的 StrucView.h中定义,为位图资源类protected:

CBitmap m_bmp;

//并应加上下面段,当然,你可在任何时候加入loadBitmap 子例程,也可加入文件资源,那由得你了!CStrucView::CStrucView()

{

VERIFY(m_bmp.LoadBitmap(IDB_BITMAP3));

}

java防止闪屏代码_防止屏幕闪烁相关推荐

  1. 计算机屏幕闪烁黑屏,显示器屏幕一闪一闪的黑屏怎么办_电脑屏幕黑屏一闪一闪如何解决...

    显示器使用久了总避免不了遇到一些故障,比如有用户反映说遇到显示器屏幕一闪一闪的,过一会就黑屏的了,这让很多小伙伴很困扰,该怎么处理呢,接下来给大家带来电脑屏幕黑屏一闪一闪的详细解决步骤. 显示器黑屏一 ...

  2. android 快速亮暗屏_Android设备闪屏怎么办?手机屏幕一会亮一会暗怎么办

    展开全部 闪屏问62616964757a686964616fe78988e69d8331333365646335题作为Android的一类常见问题,原因复杂多样.我们在这里整理一下如何分析闪屏问题,找 ...

  3. Android闪屏代码怎么写,安卓闪屏页SplashActivity的实现方法

    效果: 此gif来自https://www.jianshu.com/p/33a798ac3298,不知道怎么录gif,就在网上找了一个别人的 1.新建一个Activity,命名为SplashActiv ...

  4. java编写排序的代码_在Java 8之前,您编写了几行代码来对对象集合进行排序?...

    java编写排序的代码 在Java 8之前,您编写了几行代码来对对象集合进行排序? Java 8您需要多少个? 您可以在Java 8中用一行完成. 让我们看看下面的Employee类. public ...

  5. 前端vue后端java,Vue调用后端java接口的实例代码_亦心_前端开发者

    前段时间 做了个学校的春萌项目,其中用到 先上后端接口代码: package controller; import net.sf.json.JSONObject; import util.DBUtil ...

  6. win10蓝屏代码_电脑蓝屏代码在哪看?如何解决

    电脑蓝屏在哪看代码?知道了代码又如何解决呢?在使用电脑时难免会遇到蓝屏问题,有时重启能解决,那么重启解决不了该怎么办呢?今天小编就将查看电脑蓝屏代码方法以及解决教程分享给你们. 电脑蓝屏代码在哪看?如 ...

  7. win10蓝屏代码_?联想电脑蓝屏的解决方法教程

    联想电脑蓝屏怎么办呢?蓝屏在电脑上的出现是几乎每一个电脑小用户都会遇到的问题.首先,我们需要知道,电脑的蓝屏通常是由两种情况引起的:硬件问题或软件问题.软件问题可能是由病毒.驱动程序.软件兼容性.系统 ...

  8. java的app构建代码_适用于Java的Google App Engine,第2部分,构建杀手级应用

    java的app构建代码 存档日期:2019年5月14日 | 首次发布:2009年8月11日 像Google App Engine for Java™这样的云平台的全部要点是能够想象,构建和部署可扩展 ...

  9. 计算机桌面闪动,电脑屏幕闪动怎么解决_电脑屏幕闪烁不停抖动修复方法-win7之家...

    我们在使用电脑的过程中,难免会遇到一些关于显示器屏幕出现故障的情况,这时为了使得用户看起来比较舒服,就需要将问题进行解决,例如有的用户的电脑屏幕莫名出现闪烁不停抖动的现象,那么电脑屏幕闪动怎么解决呢? ...

最新文章

  1. 用unescape反编码得出汉字
  2. Exchange系列—使用系统自带的备份工具来备份数据库
  3. android系统镜像:boot.img kernel.img ramdisk.img system.img userdata.img cache.img recovery.img
  4. anaconda来创建python环境
  5. Less or Equal(CF-977C)
  6. 蚂蚁集团回应与腾讯微信支付竞争;华为余承东:鸿蒙现达到安卓70-80%水平;C++20 标准草案获批准| 极客头条
  7. java reactor模式例子_JAVA BIO,NIO,Reactor模式总结
  8. 二级计算机环境,计算机环境变量_二级计算机关于变量的问题
  9. php基础-基本语法
  10. SVN下载及语言包安装
  11. PHP - Smarty模板引擎 - Download下载 - 2 6 22
  12. mtk刷机显示连接服务器失败,MTK刷机常见错误分析 报错代码解释3
  13. 密码生成器(字母+数字+特殊字符)
  14. 文件删除需要管理员权限
  15. 查找论文对应开源代码的神器(Papers with Code)
  16. 关于visual studio安装失败的真正解决办法
  17. 第一台计算机作文,世界上的第一台洗衣机
  18. torch.nn.MaxPool2d详解
  19. 测试两路由器间网速软件,网速检测(TCP Monitor Plus)
  20. 压力测试与性能测试的区别

热门文章

  1. html输入符号%3e,html常用特殊符号
  2. 深度学习与生成式模型
  3. react中添加背景音乐
  4. Easyrecovery12.0.0.2 官方中文版下载
  5. 3D打印机加工一般可以打印什么东西
  6. 空指针引用故障(空指针解引用)
  7. 求生之路2 局域网联机教程
  8. 常见的RuntimeException有哪些
  9. 2018-2019-2-20175327 蜂凯南 实验三 《敏捷开发与XP实践》实验报告
  10. 浏览器本地存储-localStorage的介绍和使用