现在的位置: 首页 > 综合 > 正文

windows用户界面编程中的界面闪烁问题

2013年10月17日 ⁄ 综合 ⁄ 共 3211字 ⁄ 字号 评论关闭

在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函数速度非常快,足以在屏幕的刷新周期内完成绘图,这样能基本上避免闪烁。

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

   本文免费附送个人简历

袁永福,男,170厘米,体重66千克,江西省九江市都昌县人,于2001年从南京东南大学动力工程系本科毕业,毕业后一直在南京从事计算机软件研发,主要使用微软技术,不敢言精通,但也能拍着胸脯说相当熟悉,其看家语言为vb,vb.net和c#,此外还熟悉xml,xsl。能比较了解和使用javascript和vba。进行过win32api编程和gui编程。有比较多的图像化用户界面编程经验。在目前工作的单位中担当项目经理,独立负责过一些有相当技术难度的项目研发。工作4年中完成的项目有

  • 2002年,某小程式,独立vb编写,3000行代码,使用控件来实现windowsnt的服务程式。
  • 2002年,某公司信息系统,为asp.net应用,c#编写,15000行代码,使用ms sql server 数据库。本工程是其他人员研发,但由于种种原因无法完工,由我接手进行强制收尾,现该系统比较稳定的运行了2年
  • 2002年,某模板编制程式,独立vb.net编写的图像化用户界面程式,50000行代码,实现了类似vs.net的窗体设计器的功能,并能自动生成和设计样式非常接近的html文件和配套的xsl文件,
  • 2003年,某打印模板编制程式,独立用vb编写,60000行代码,实现了打印模板的编制,包括打印样式和数据源的设计,并在进行打印时使用xsl转换来生成打印文件
  • 2004年,某文本编辑器,独立用c#编写,64000行代码,从底层做起实现了一个带格式的文本编辑器,并在文本编辑器中添加了非常多特性。
  • 此外还编写了一些小程式,扫在一起也有不少代码。

本人对计算机软件研发有着相当的兴趣,并比较看好中国软件行业的大前景。本人学习能力强,思维敏捷,比较牢固的掌控面向对象的编程思想,并有着相当的创新精神,喜欢研究性的软件研发。虽然本人主要使用微软技术,但对java技术也保持着相当的学习态度,对mvc模式,j2ee框架有所了解,能修改已有的jsp页面或java程式。

本人现和当前公司的合同快到期,因此现寻求新的雇主,希望能在南京工作,待遇可。有兴趣者可联系我,联系方法为

电子邮件: yyf9989@hotmail.com , qq号:28348092

抱歉!评论已关闭.