C语言中绘图时闪烁的问题

    这几天公司相关的设备软件要做新版本release的最后检测工作,大问题没有,但是出现了两个细节的问题:一个是在等待元件进入设备的时候整个屏幕呈现出了明显的低频闪动,另外一个问题是在元件检测的工程中屏幕内的某个区域出现了高频的快速刷新,重绘的循环过程,从而导致了高频闪动。这两个问题其实并不算逻辑性的bug,只是会造成一些视觉上的不适(设备是自动化检测设备,其实也不需要操作员实时的在产线上)。但是这恰恰戳中了我刨根问底的那股劲儿,我决定对代码做一次review,找到问题的根源。

    认真分析了代码,我发现了同事在合并一些新功能代码的时候,忽略了一些细节:

    首先是在设备waiting的阶段,为了更新一些实时的数据,同事在某个循环中加入了如下的语句

	InvalidateRect(hWnd,NULL,FALSE);
	UpdateWindow(hWnd);

    这是两行代码适用于刷新指定区域的窗口。InvalidateRect用于使指定句柄区域失效,之后才能通过updatewindow重新绘制指定的句柄的区域。两者必须配合使用才能实现页面的刷新。用法是没有问题的,但是在循环中使用的时候要注意,如果要做更新的内容较多(例如整个屏幕,而且信息较多)的话,加之更新的较为频繁,很容易会出现明显的本文所提到的第一个问题,即出现屏幕低频的闪动。

    解决思路:(1)当然就是去除冗余的uptdatewindow的代码(2)不得不在循环中使用updatewindow的时候,注意添加一些判定条件,当页面有更新信息的时候再进行update。我采用了后者,哈哈,解决了一个问题。

解决了第一个后再次分析代码,发现了第二个问题发生的原因:同样是发生在一个循环中。这次采用的是TextOut函数,只重绘一小块区域。大致的代码大意如下:

while(result==SEQ_KEEPWAIT)			
	{
		result=WaitResult(hWnd,targetStat,0);
	}
	int WaitResult(HWND hWnd,int targetStat,int iTimeOutLimit)
	{
		...
		strcpy(buf,"                 ");//先清空上次的内容
		strcpy(buf1,"1234567890");//此次要绘制的内容
		TextOut(hDC,(DISPLAY_X+112),150+TOOLBAR_HEIGHT,buf,strlen(buf));//先清空上次的内容
		TextOut(hDC,(DISPLAY_X+112),150+TOOLBAR_HEIGHT,buf1,strlen(buf1));//此次要绘制的内容
		if(iTimeOutLimit==0)
    		return SEQ_KEEPWAIT;
		...

	}

    可以看出此处的timeout的值被设为了0,这么设计导致了函数高速的进行了区域重绘(不知道哪个同学这么设置的参数,估计他的初衷是想加快程序速度)。理论上说如果计算机运行代码的速度为0的话,这样的设计是没任何问题的,但是实际上通过查询资料,发现不少同学遇到了这样的问题,有大神说是显卡的刷新速度有限造成的。以下为网上转载信息:调用GDI函数向屏幕输出的时候并不是立刻就显示在屏幕上只是写到了显存里,而显卡每隔一段时间把显存的内容输出到屏幕上,这就是刷新周期。 一般显卡的刷新周期是 1/80秒左右,具体数字可以自己设置的。这样问题就来了,一般画图都是先画背景色,然后再把内容画上去,如果这两次操作不在同一个刷新周期内完成,那么给人的视觉感受就是,先看到只有背景色的图像,然后看到画上内容的图像,这样就会感觉闪烁了。

    讨论之后,我们的解决方案比较直接,在不影响运行速度的情况下加了10ms的延时,发现闪烁消失,更奇怪的是程序运行的效率得到了一定幅度的提升。也是意想不到的收获。

    这次问题的修改得到了新的一些启示: 
      (1)善用延迟。短延时有的时候对于程序的运行不一定是负担,合理的设计反而可能提高效率。
      (2)慎用绘图。对于底层设计者而言,时不时的画面进行绘制操作是必不可少的,但是更要注意绘图代码所处的位置,以及重绘的逻辑。否则造成界面的不友好是一方面,如果影响了代码运行的效率的话,那就真的是“化蛇添足”了。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值