当前位置:天才代写 > tutorial > C语言/C++ 教程 > BitBlt()双缓冲办理图象闪烁

BitBlt()双缓冲办理图象闪烁

2017-11-05 08:00 星期日 所属: C语言/C++ 教程 浏览:672

副标题#e#

显示图形如何制止闪烁,如何提高显示效率是问得较量多的问题。并且大都人认为MFC的画图函数效率很低,老是想寻求其它的办理方案。

MFC的画图效率简直不高但也不差,并且它的画图函数利用很是简朴,只要利用要领恰当,再加上一些能力,用MFC可以获得效率很高的画图措施。

我想就我恒久(呵呵虽然也只有2年多)利用MFC画图的履历谈谈我的一些概念。

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

这样配景没有了,功效图形显示简直不闪了,可是显示也象前面所说的一样,变得一团乱。怎么办?这就要用到双缓存的要领了。双缓冲就是除了在屏幕上有图形举办显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形凭据一个点一个点地包围到屏幕上去(这个进程很是快,因为长短通例整的内存拷贝)。这样在内存中画图时,随便用什么反差大的配景致举办排除都不会闪,因为看不见。当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形不同很小(假如没有举动,虽然就没有不同),这样看起来就不会闪。


#p#副标题#e#

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、如何提高画图的效率

#p#分页标题#e#

我主要做的是电力系统的网络图形的CAD软件,在一个窗口中往往要显示成千上万个电力元件,而每个元件又是由点、线、圆等根基图形组成。假如然要在一次重绘进程重画这么多元件,可想而知这个进程长短常漫长的。假如加上了图形的欣赏成果,鼠标拖动图形转动时需要举办大量的重绘,速度会慢得让用户将无法忍受。怎么办?只有再研究研究MFC的画图进程了。

实际上,在OnDraw(CDC *pDC)中绘制的图并不是所有都显示了的,譬喻:你在OnDraw中画了两个矩形,在一次重绘中固然两个矩形的绘制函数都有执行,可是很有大概只有一个显示了,这是因为MFC自己为了提高重绘的效率配置了裁剪区。裁剪区的浸染就是:只有在这个区内的画图进程才会真正有效,在区外的是无效的,纵然在区外执行了画图函数也是不会显示的。因为大都环境下窗口重绘的发生大多是因为窗口部门被遮挡可能窗口有转动产生,改变的区域并不是整个图形而只有一小部门,这一部门需要改变的就是pDC中的裁剪区了。因为显示(往内存可能显存都叫显示)比画图进程的计较要费时得多,有了裁剪区后显示的就只是应该显示的部门,大大提高了显示效率。可是这个裁剪区是MFC配置的,它已经为我们提高了显示效率,在举办巨大图形的绘制时如何进一步提高效率呢?那就只有去掉在裁剪区外的画图进程了。可以先用pDC->GetClipBox()获得裁剪区,然后在画图时判定你的图形是否在这个区内,假如在就画,不在就不画。

假如你的画图进程不巨大,这样做大概对你的画图效率不会有提高。

 

    关键字:

天才代写-代写联系方式