http://yyf9989.cnblogs.com/archive/2005/09/02/228320.html

Windows用户界面编程中的界面闪烁问题
南京千里独行版权所有转载请保留本信息

在Windows图形化用户界面编程中,若程序自己绘制用户界面时,会经常碰到界面闪烁,比如其他窗口在上面移动,用户界面滚动,这些都有可能导致闪烁。在一个容器中绘制特定的文档,需要相应作为绘图容器的控件的OnPaint事件,需要在OnPaint事件处理中重新绘制文档,而Windows操作系统一般会在两种情况下触发OnPaint事件:容器控件被其他窗体覆盖后又显示,还有就是容器控件的滚动处理。在这些情况下,Windows操作系统会频繁的触发OnPaint事件,而应用程序会频繁的在绘图容器中重新绘制图形,若应用程序没有进行很好的优化,则很有可能导致用户界面闪烁。

用户界面出现闪烁自然害处多多,首先它使得你的程序看起来不专业,甚至有不稳定的嫌疑,对于追求完美的你这么会容许它的存在呢;其次闪烁会损害用户的视力,容易让用户产生视觉疲劳。

好了,废话我不多说了,我们就来发现问题,分析问题,解决问题。

首先说说闪烁的本质,说到本质,就不得不提一些计算机系统结构和Windows图形用户子系统的一些知识。我们知道,在计算机内存中有一个区域叫做显存,而显卡则每过一些毫秒就从扫描显存,然后根据操作显示器来绘制一个个象素,因此每过一些毫秒显示器显示的内容就会重新设置一遍,由于这是硬件操作,非常快,若画面内容没有变化,则人类肉眼是看不到这个刷新的,此时用户界面是没有任何闪烁。

    右图就是应用程序绘制用户界面的原理,应用程序在CPU的支持下向显存填充数据,而以此同时显卡也从显存加载数据操作显示器绘制图形,(笔者想若应用程序能直接访问显示器则绘制速度不要太快哦),而用户界面闪烁也就根源于这种显示结构。前面提到,显卡每过一些毫秒就会扫描显存,刷新显示器的显示。假设有个显示卡,设置其刷新频率为50赫兹,则它每20毫秒就扫描显存刷新显示器,而显卡的操作和应用程序的操作之间没有任何关系,显卡是自带处理器的,于是应用程序和显卡这两个对象同时操作显存,显卡只读取显存,而应用程序则修改显存,这就导致了类似多线程程序的数据同步的问题了。但这时硬件结构决定此时没有什么锁定机制可使用。显卡每20毫秒就进行刷新操作,连操作系统也挡不住,而且应用程序根本不知道显卡会何时进行刷新操作。

某个时刻,应用程序需要绘制用户界面,首先需要清空绘制容器,因此将显存一大片区域设置为白色,应用程序刚完成了清空操作,还每来得及绘制内容时,显卡就刷新了,很快显示器上显示了一大片白色。同时,应用程序开始绘制内容,应用程序运行缓慢,它化了20毫秒绘制了文档的上半身,文档上半身主要为红色,刚绘制了上半身,显卡就好不留情的进行刷新,很快显示器上显示了一半的文档,刚才一半的白色大半变成了红色,此时用户看来,显示器一下变成一片白,然后很快一半变成红色,此时显示器内容产生了两次大面积的内容变幻,然后应用程序又化了20毫秒显示了文档的下半身,文档下半身主要为绿色,此时显卡进行刷新,显示器上另一半还残存的白色又变成绿色。由于应用程序绘制文档完毕,因此不再修改显存,此时显示器的显示的内容不再发生改变。

在上面的描述中,显示器首先从花花绿绿变成一片白,20毫秒后一半变成红色,又20毫秒后另一半变成绿色,如此大面积的显示内容短期的改变就是所谓的闪烁,此时计算机显示器就是在折磨用户的眼睛。

其实从广义上说,计算机显示器显示的内容频繁的发生大面积的改变都是考验人类的眼睛。有些人玩一些激烈的3D游戏,比如雷神CS之类的,若玩的时间长点眼睛就受不了。就是因为这些游戏程序导致显示器显示的内容频繁的发生大面积的改变。因此游戏程序也算导致用户界面闪烁。只不过这种闪烁不算难受。

通过上面的讨论,知道了闪烁的根源,于是我们发现了问题,并分析了问题,现在解决问题。在目前的计算机结构中,我们的应用程序只能通过填充显存来绘制用户界面,在这种情况下,对付闪烁的不二法则就是快,应用程序要非常快的修改显存。对于每20毫秒进行刷新操作的显卡,若我们的应用程序能在20毫秒内修改显存完毕,则在很多情况下显卡就只会导致显示器显示的内容发生改变,减少闪烁,应用程序填充显存前后显存的数据进行对比,若数据前后不一致的字节数越少,显示器中刷新操作前后颜色发生改变的象素数就越少,这用户界面的闪烁就越小。

提高应用程序修改显存的速度的方法有很多中,而且Windows操作系统为我们做了许多底层的操作。我们知道若一个窗体被覆盖后又显示了,则Windows操作系统就会向该窗体发送重绘消息,而且还会传一个矩形数据,该矩形表示窗体中需要刷新的区域,应用程序可以根据这个矩形来重新绘制文档的某个部分,这样就不必要绘制所有的内容,提高绘制速度,减少绘制时间,这就需要进行绘图代码的优化。

在某些情况下,绘图速度很难优化起来,此时可以采用所谓“双缓冲”的技术来减少闪烁,应用程序可以在内存中创建一个和屏幕相兼容的图形设备上下文。该上下文实际上处理一个保存在内存中的BMP图片对象,这样就容许应用程序缓慢地在这个BMP上绘制图形。应用程序绘制完毕,就用WIN32API函数BitBlt来将BMP图片填充到显存中,BitBlt函数速度非常快,足以在屏幕的刷新周期内完成绘图,这样能基本上避免闪烁。但双缓冲也有缺点,首先增加程序复杂度,其次要消耗一些内存,还有它让整个绘图时间变长,导致用户进行滚动时会产生“界面沉重感”,有“惯性”,此外还让人偷懒而不注意绘图操作的优化。

俗话说,说得容量做到难,编程也一样,本文中对付闪烁的说的轻巧,但在实际编程中,闪烁一直是图形化用户界面编程的老大难问题,需要精心的设计程序结构,优化代码,提高速度。这需要靠很多的理论知识和深厚的编程功底,这些需要长期的编程实践。

posted on 2005-09-02 00:17 千里独行 阅读(2025) 评论(8) 编辑 收藏

#1楼 2005-09-02 00:27 birdshome

评论

389596

理论说的通俗易懂,再能来些实际经验和解决方案就完美了:)
 回复 引用 查看   
#2楼[楼主] 2005-09-02 00:31 千里独行      
有演示代码,http://blog.csdn.net/yyf9989/archive/2005/07/02/410328.aspx
 回复 引用 查看   

#3楼 2005-09-02 07:46 dudu      
图片不能显示, 建议上传图片, 不要从其他网站链接。
 回复 引用 查看   

#4楼 2005-09-02 08:09 waxwork3      
说得明白!
可又不得不去翻Win32API.:-<
 回复 引用 查看   

#5楼 2005-09-02 08:28 lovebanyi[未注册用户]
又缓冲游戏中运用的比较多吧.

人的眼睛一般75HZ以上才不会感到闪烁.也就是13.33MS
 回复 引用 

#6楼 2005-09-02 15:55 AlleNny      
双缓冲一般的界面编程也要用到,否则闪烁也很厉害,不过幸运的是DotNet帮我们弄好了,不要自己操心啦。
 回复 引用 查看   

#7楼 2005-12-18 20:53 R.J.W.      
DotNet的WinForm自动使用双缓存,直接刷新,不闪的(才是健康的!)。
我一般使用图片缓存,更快,更方便。:)
 回复 引用 查看   

#8楼 2006-04-30 17:13 amursoft[未注册用户]
"Avail GUI+ 图形用户界面开发软件1.0"提供了一整套机制和工具帮助开发基于Windows的图形用户界面,自动解决了用户界面闪烁问题。使用该软件,应用程序基本上不用绘图,只要用图形对象描述就可以了。
感兴趣的话可以到http://www.amurtech.com/download.htm下载。
 回复 引用   

Windows用户界面编程中的界面闪烁问题相关推荐

  1. 如何解决QT视频会议窗口在拉伸过程中整个界面闪烁的问题

    一.问题描述 开发环境:Qt5.15.0.Win10. Visual studio 2019.C++ 在开发视频会议项目的过程中,被一个问题困扰了很久.就是整个视频会议的界面在拉伸四周改变大小的过程中 ...

  2. Windows DLL编程中的导入导出:__declspec(dllimport) ,__declspec(dllexport) ,

    在Windows DLL编程时,可使用__declspec(dllimport)关键字导入函数或者变量. 函数的导入 当你需要使用DLL中的函数时,往往不需要显示地导入函数,编译器可自动完成.但如果你 ...

  3. Windows图形编程 中的一个例程所引发的收获和思考

    作者:朱金灿 来源:http://blog.csdn.net/clever101/ 袁峰大侠著的<Windows图形编程>是一本学习<Windows图形编程>的好书.书中的第二 ...

  4. htc Vive中VR界面闪烁的解决

    如果相机上挂有 Screen Space Ambient Obscurance ,在头盔上看时,会出现镜头抖动效果 FR:海涛高软(QQ技术交流群:386476712)

  5. java动画闪烁_优化Java动画编程中的显示效果

    Java动画编程有多种实现方法,但它们实现的基本原理是一样的,即在屏幕上画出一系列的帧来造成运动的感觉.Java多线程技术是Java动画编程中普遍运用的技术,它在控制动画程序的流程和动画的显示效果方面 ...

  6. 《windows核心编程系列》十八谈谈windows钩子

    windows应用程序是基于消息驱动的.各种应用程序对各种消息作出响应从而实现各种功能. windows钩子是windows消息处理机制的一个监视点,通过安装钩子能够达到监视指定窗体某种类型的消息的功 ...

  7. python预处理c语言_详解C语言编程中预处理器的用法

    预处理最大的标志便是大写,虽然这不是标准,但请你在使用的时候大写,为了自己,也为了后人. 预处理器在一般看来,用得最多的还是宏,这里总结一下预处理器的用法. #include #define MACR ...

  8. 优化Java动画编程中的显示效果

    优化Java动画编程中的显示效果 作者:赵福军 曹代勇 李青云 发文时间:2002.11.12 09:32:33 Java动画编程有多种实现方法,但它们实现的基本原理是一样的,即在屏幕上画出一系列的帧 ...

  9. c++ windows网络编程--udpSocket之recfrom()函数阻塞问题

    在windows网络编程中,创建udp socket,然后调用recfrom()函数进行数据接收,发现当没有数据发送来时,会一直阻塞在recfrom()里面.为了避免因阻塞而占用CPU资源,所以不能一 ...

最新文章

  1. 在Ubuntu 14.04上设置生产环境可用的Node.js
  2. R语言dataframe分组数据汇总(aggregate and sum):类似于excel的sumif函数
  3. html模板存储在mysql_Python爬虫架构5模板 | 你真的会写爬虫吗?
  4. opencv表面缺陷检测_彩钢板表面缺陷在线检测--Smart Vision
  5. 【Shall脚本】定时在线备份上传
  6. IBM X3650 WIN2003安装详细方法
  7. 怎么解决深入学习PHP的瓶颈
  8. python 求一个矩阵的距离矩阵的方法:
  9. 字节3-1前端面试官自学Vue的正确姿势
  10. [css] 移动端页面不满一屏时如何实现满屏背景?
  11. vb如何定义微软服务器stul,VBScrip微软官方教程.doc
  12. Win11系统自动暂停更新后想继续怎么办 Win11系统重新启动更新教程
  13. 百分百储值卡回收网站源码+手机模板
  14. 七.激光SLAM框架学习之A-LOAM框架---速腾Robosense-16线雷达室内建图
  15. 三角网格上高斯曲率和平均曲率
  16. php-java-net-python-刺绣添加厂商信息计算机毕业设计程序
  17. 树莓派raspi-config配置工具
  18. php 鼠标 移动 手型,css各种手型集合(css禁止手型)
  19. windows 没有应用商店,直接安装所需应用的解决方案
  20. 树莓派串口配置(c++)

热门文章

  1. Vue 中的 ref 属性详解
  2. 构建数字经济新生态,和数区块链结合隐私计算可发挥作用
  3. 电视剧名校分集剧情介绍二
  4. 3dsmax中计算机快捷键大全,【1人回答】3DMax打开计算器的快捷键是什么?-3D溜溜网...
  5. 腾讯汤道生:产业互联网开放生态已初步形成,2021加大SaaS生态建设|CEO说
  6. k8s 部署 TCP node应用
  7. 斥资建造全景分割养猪场,AI 养猪,到底靠不靠谱?
  8. Linux PPP 实现源码分析
  9. MATLAB中图像处理的函数
  10. 基于朴素贝叶斯和LSTM的两种新闻文本分类方法