基于双缓存技术解决某模拟系统实时显示屏幕闪烁的方法

时间:2022-08-06 09:57:04

基于双缓存技术解决某模拟系统实时显示屏幕闪烁的方法

摘要:本文基于双缓存技术,对某模拟系统实时图形绘制和实时数据显示时,屏幕闪烁难题的一种解决方法进行了探索。分析了计算机显示的原理,阐述了双缓存技术的实质、运用步骤和注意事项,并在Windows操作系统和Visual C++6.0开发平台上,通过实例编程、上机试验,检验了该方法的有效性。

关键词:双缓存;实时显示;屏幕闪烁;方法

中图分类号:TP311文献标识码:A文章编号:1009-3044(2008)25-1574-03

One Way Based on Double Buffer Memory Technology to Solve Some Simulator Real-time Display Screen Flickering

DONG Yan, ZHOU Yan-ming, CUI Wei-bing

(Department of Science and Technology, College of Chinese PLA Artillery, Hefei 230031, China)

Abstract: Based on double buffer memory technology, the paper studies one way to solve some simulator screen flicker upon real-time protracting figure and real-time displaying data. After analyzing computer display theory, it expounds double buffer memory technological substance, application steps and notices, and proves validity of this method through programming, testing an example, utilizing Windows operation system and Visual C++ 6.0 exploit platform.

Key words: double buffer memory; real-time display; screen flickering; method

1 引言

某模拟系统的模拟对象之一是监视雷达天线,其扫描周期为1秒或1.5秒,也就是说雷达天线每转一圈,探测数据和探测数据曲线至少要在1秒之内,刷新终端显示器1次,这就对模拟系统的数据处理模块程序提出了很高的要求。如何实现实时图形绘制和实时数据显示,并解决屏幕闪烁的难题,是该模拟系统软件开发要重点解决的关键问题之一。

在屏幕显示区域,要实时显示探测数据,并要实时绘制和显示图形,如果直接在屏幕上动态绘图,屏幕就会明显的闪烁。这是因为图形绘制过程,可分为绘制、擦除、重绘三个阶段[1],其中擦除窗口显示区的操作是必须的,而在新的图形绘制出之前,在极短时间内,屏幕呈现的是一个空的显示区域,完成图形重绘后,窗口显示区中才开始有内容显示,如果擦除和重绘的操作间隔时间过长,就会出现闪烁,这就是造成屏幕闪烁的根本原因。使用双缓冲技术可有效的防止这种闪烁现象。下面首先简要介绍计算机显示原理和双缓存技术。

2 计算机显示原理

计算机显示系统的核心是视频内存。该内存包含有代表显示图案的数据,而这些图案显示在显示器上。每一个图形操作都会影响视频内存,因为GDI[2](Graphic Device Interface)执行计算后,以相应的方式更改视频内存,即显示在屏幕上。

相对于视频内存的位图内存,二者区别在于,位图内存是看不到的,而视频内存可以看到。位图代表类似于视频内存的RAM区域,由于它们都代表一个容纳数据的内存地址,因此二者又是相似的。由位图分配的RAM代表一个矩形。在Windows API[3]中,所分配内存的句柄被称为HBITMAP。数据驻留在此内存中,一旦被移动到视频内存中,就显示在显示器上。例如:一个桌面图标,图标从磁盘加载到内存中,然后内存被移动到视频内存的恰当位置,这样当视频内存通过视频硬件被显示到屏幕上时,图标则可见。

位图以不同于诸如绘制直线或椭圆这样的对象的方式,将图形对象添加到屏幕上。直线和椭圆是以数学方法计算,然后按照对象显示方式设置视频内存中的象素。位图数据不用计算,图案已经存在于位图内存中。只需要将存储块从位图内存拷贝到视频内存中即可。因此,当最终结果是一个复杂的图形时,使用位图比使用一系列绘图操作要好的多。例如:在屏幕上绘制你的照片需要执行很多次独立操作,可能是成千上万,但是通过使用位图,复杂照片可以驻留在位图内存中,然后只需要执行一次拷贝操作,位图内存就可以被快速的复制到视频内存的一个区域中,这样照片就可以显示在屏幕。

当程序绘制窗口需要多次调用GDI时,在窗口擦除并被重新绘制的过程中,会出现明显的屏幕闪烁。这是由于Windows操作系统在每次重新绘制窗口时,首先要用指定的背景色来擦除当前窗口的内容,然后再把新的窗口内容绘制上去。使用双缓存技术可以解决屏幕闪烁。

3 双缓存技术

在计算机系统中,缓存[4]就是一个开辟用来保存数据的临时空间,使用缓存,就不需要频繁的访问存储在内存或硬盘中的数据,当执行一个或一系列的操作,并且将操作结果放入缓存后,就可以迅速的访问这些数据。

3.1 双缓存技术的实质

双缓存技术就是先在内存(不可见缓存)中操作,然后再把操作结果拷贝到屏幕内存(可见内存)中进行显示的技术。应用双缓存技术实时显示图形,观察到的是图形操作的结果,而不是图形的绘制过程。

该技术涉及到两个设备上下文(Device Context,简称DC):屏幕DC和内存DC。所谓设备上下文[5](DC)就是一种Windows数据结构,它包括了一个设备(如显示器)绘制属性的相关信息。把所有要绘制的内容先在内存DC中进行绘制,而后全部拷贝到屏幕DC中,从而把所有琐碎的绘制过程都在内存DC中完成,用户在屏幕上看到的就是一个完成的图形。关键就是这个图形,这个图是从屏幕DC中创建的,该图的尺寸就是客户区域的大小,之后,把该图选入内存DC中,然后在内存DC中绘制的动作都是在这个图中进行的,最后把内存DC中,这幅已经绘制好的图形再选入到屏幕DC中,即显示出来。

3.2 应用双缓存技术的一般步骤

运用双缓存技术一般可以分为六个步骤:

1) 利用CDC类的成员函数CreateCompatibleDC()创建关于屏幕的内存DC;

2) 创建一幅关于屏幕DC的图形,注意把握rect的尺寸为客户区域大小;

3) 利用CDC类的成员函数SelectObject()将这幅画选入内存DC中;

4) 在内存DC中进行任何绘制动作;

5) 绘制完成后,利用CDC类的成员函数BitBlt()或StretchBlt()将内存DC中的这幅图拷贝到屏幕DC中来;

6) 进行相关的资源回收动作,以免造成内存泄漏。

3.3 应用双缓存技术的注意事项

在运用双缓存技术的过程中,如果系统频繁刷新背景,将会直接影响屏幕的实时显示。因此,必须强制要求系统不刷新背景,从而加快显示速度。具体做法是重载系统的ON_WM_ERASEBKGND消息响应函数,令其返回值始终为FALSE。

另外,调用刷新函数Invalidate会导致整个窗口的图形重绘,需要的时间较长,而函数InvalidateRect()只重绘Rect结构所指的矩形区域,所需的时间会少一些。因此在刷新时,采用只刷新指定区域的方式,以减少计算量。

4 基于双缓存技术的实时曲线绘制和数据显示

4.1 开发环境

1) 操作系统:Windows;

2) 开发平台:Visual C++ 6.0。

4.2 关键代码

//创建内存绘图区

m_dcCompatible.CreateCompatibleDC(pdc);

m_bitmap.CreateCompatibleBitmap(pdc,rect.Width(),13*rect.Height());

m_dcCompatible.SelectObject(&m_bitmap);

m_bitmap.GetBitmap(&m_bmp);

以球坐标数据和球坐标曲线的实时绘制为例说明在内存DC中的绘制动作:

void CJsDlg::OnSetTextQ()

{

……

CDC *pDC=&m_dcCompatible;//定义CDC类对象

//////////实时显示球坐标数据

for(int j=0;j

{pDC->TextOut(m_RulerWidth,tm.tmHeight+j*tm.tmHeight,Qd[j][0]);

pDC->TextOut(m_RulerWidth+90,tm.tmHeight+j*tm.tmHeight,Qd[j][1]);

……

}

……

//////////实时绘制球坐标曲线

for(int i=0;i

{

int y=3*rect.Height()-rect.Height()/10*2-(i+1)*Qperheight-8;

pDC->SetPixel(zeroscaleYj+(int)(Qsj[i][0]*perscaleYj),y,RGB(0,0,255));

//仰角曲线

pDC->SetPixel(zeroscaleFwj+(int)(Qsj[i][1]*perscaleFwj),y,RGB(0,255,0));

//方位角曲线

pDC->SetPixel(zeroscaleXj+(int)((Qsj[i][2]*perscaleXj)/1000),y,RGB(255,0,0));

//斜距曲线

}

……

}

绘制完后利用CDC类的成员函数StretchBlt()将内存DC中的这幅图绘制到屏幕DC中来。这里自定义成员函数DrawPages()实现这一功能。

void CJsDlg::DrawPages()

{

pdc->StretchBlt(0,-m_vScrollBar_Pos*rect.Height()/m_PageSize,rect.Width(),

rect.Height(),&m_dcCompatible,0,0,m_bmp.bmWidth,m_bmp.bmHeight/13,

SRCCOPY);

pdc->StretchBlt(0, rect.Height()-m_vScrollBar_Pos*rect.Height()/m_PageSize, rect.Width(),

rect.Height(),&m_dcCompatible,0,rect.Height(),m_bmp.bmWidth,m_bmp.bmHeight/13,

SRCCOPY);

pdc->StretchBlt(0,2*rect.Height() - m_vScrollBar_Pos*rect.Height()/m_PageSize,

rect.Width(), rect.Height(),&m_dcCompatible,0,2*rect.Height(),m_bmp.bmWidth,

m_bmp.bmHeight/13,SRCCOPY);

……

}

4.3 程序实现

如图1和图2所示,分别为实时数据显示和实时曲线显示效果图。在程序运行的显示过程中,可以明显的感受到运用双缓存技术后,解决了屏幕闪烁的问题,实时曲线绘制和实时数据显示流畅。

图1 实时数据的显示 图2 实时曲线的显示

5 结束语

在软件开发的过程中,实现数据和图形的显示比较简单,但是要实现实时的图形绘制和实时的数据显示,同时避免屏幕的闪烁却并不容易,本文经过理论分析、实例验证,提供了一种基于双缓存技术解决实时显示屏幕闪烁的有效方法。

参考文献:

[1] 孙家广. 计算机图形学[M]. 3版. 北京:清华大学出版社,2003.

[2] Mahesh Chand. GDI+图形程序设计[M]. 北京:电子工业工业出版社,2005.

[3] 杨旭, 沈大林, 沈昕, 等. Visual C++ 6.0编程篇[M]. 北京:电子工业出版社,2004.

[4] 潘云鹤. 计算机图形学原理、方法及应用[M]. 北京:高等教育出版社,2002.

[5] 朱晴婷, 黄海鹰, 陈莲君. Visual C++程序设计[M]. 北京:清华大学出版社,2005.

上一篇:基于SVM的中文新闻评论的情感自动分类研究 下一篇:AVS视频编解码标准中预测编解码技术的硬件设计...