我做了一个单文档MFC程序,在背景上加载了一个bmp图像资源,因为程序需要在改背景上用Rectangle(CRect(0,0,412,311))设置一个区域,并不断滴刷新该区域,为了防止bmp背景的闪屏,我就用双缓冲技术加载了该bmp,然后又在该背景上绘制我要动态刷新的区域【即是上面用Rectangle(CRect(0,0,412,311))产生的区域】,发现该区域有闪烁。我就想是否可以再次用双缓冲技术来绘制该区域,但是我发现这样做以后它还是有闪烁。
我的问题是:1.这样做是否思路本身就是错的?请详细解释一下这个错误出在哪里,谢谢!
2.我是否可在已经加载进来的bmp背景上对闪烁区域单独做出某些处理,比如重载OnEraseBkgnd()函数等(我发现这种也是无法解决问题的)思路去解决该问题,烦请给出具体思路或提示代码,谢谢!
3.这是我想到的另一种解决思路,向单文档中导入(用非双缓冲技术)bmp做背景,然后在背景上再用双缓冲技术绘制我要不断刷新的区域?但是关键我不知道如何使导入的bmp作为背景,并使我要的区域能真正地在此bmp背景上重绘,请给予赐教?
我的问题是:1.这样做是否思路本身就是错的?请详细解释一下这个错误出在哪里,谢谢!
2.我是否可在已经加载进来的bmp背景上对闪烁区域单独做出某些处理,比如重载OnEraseBkgnd()函数等(我发现这种也是无法解决问题的)思路去解决该问题,烦请给出具体思路或提示代码,谢谢!
3.这是我想到的另一种解决思路,向单文档中导入(用非双缓冲技术)bmp做背景,然后在背景上再用双缓冲技术绘制我要不断刷新的区域?但是关键我不知道如何使导入的bmp作为背景,并使我要的区域能真正地在此bmp背景上重绘,请给予赐教?
如果你真正理解双缓存的意义的话,导入BMP就是同样的道理
我记得的步骤是
1.建立2个cdc,A与B,A使用selectobject所要选取的BMP
2.B使用bitblt或者stretchblt根据自己的需要从内存中画出A这时候A就是所画的背景了。
大致步骤就是如此,双缓存核心的就是思想。思想不明白就理解不了代码的意义
dcMemory.CreateCompatibleDC(pDC);
CBitmap bmp1;
bmp1.LoadBitmap(IDB_YS_BITMAP); //载入位图
BITMAP bmpInfo1;
bmp1.GetBitmap(&bmpInfo1); //获取位图
CBitmap *pOldBitmap=dcMemory.SelectObject(&bmp1);
pDC->BitBlt(0,0,bmpInfo1.bmWidth,bmpInfo1.bmHeight,&dcMemory,0,0,SRCCOPY); //将载入的位图复制到当前窗口中
::AfxGetMainWnd()->SetWindowPos(NULL,0,0,bmpInfo1.bmWidth,bmpInfo1.bmHeight+100,SWP_NOMOVE);//使窗口与位图大小相当
CDC MemDC; //首先定义一个显示设备对象
CBitmap MemBitmap;//定义一个位图对象 MemDC.CreateCompatibleDC(pDC);//随后建立与屏幕显示兼容的内存显示设备
MemBitmap.CreateCompatibleBitmap(pDC,412,311);//下面建立一个与屏幕显示兼容的位图 //将位图选入到内存显示设备中
//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap); //绘制游戏区域,出现闪烁是因为下面的的矩形区没有利用双缓冲技术?
CPen yspen;
yspen.CreatePen(1,8,250); //创建颜色与背景相近的画笔
MemDC.SelectObject(&yspen);
MemDC.Rectangle(CRect(0,0,412,311)); //绘制边框
// pDC->SelectObject(&yspen);
// pDC->Rectangle(CRect(343,138,755,449)); //绘制边框 //将内存中的图拷贝到屏幕上进行显示
// MemDC.BitBlt(343,138,755,449,&MemDC,0,0,SRCCOPY);
pDC->BitBlt(343,138,755,449,&MemDC,0,0,SRCCOPY); //绘图完成后的清理
bmp1.DeleteObject();
dcMemory.DeleteDC();
MemBitmap.DeleteObject();
MemDC.DeleteDC();
只要双缓冲用的正确不管多快都不会闪
我觉得应该是代码和应用有问题
比如是不是OnEraseBkgnd没有处理
或者是在背景的基础上又进行绘图————这样就不是双缓冲了
1. “图A(paint)->图B(paint),如果中途出现个第三态图C(EaraseBkgrnd)”, 并且有延迟就会有闪烁. 也就是不是直接图A->B. 中间态会让用户感觉到是闪烁.
2. “图A(paint)->图B(paint)是连续的, 但是图A和图B差别很大,并且刷新频率很高”, 也可能让用户感觉到不是闪烁, 而是画面有模糊的时候. 不是图A的状态也不是图B的状态, 而是图A和图B混合的状态, 影响效果.
(Reborn)
的回答给了我一些思路,双缓冲技术的思想是在内存里绘制再显示,我其实不需要去刷新我的bmp背景,我的目的是要刷新我的前景(即长方形区域),但是当我改变单文档窗体的大小或拖动时,bmp背景会被重绘,这是我对背景采用双缓冲技术的初衷,我觉得你说的少用刷新的函数我试了重绘在长方形中移动目标,发现重绘显示目标时,仍然有闪屏出现,像上面的代码所示,问题依旧,求教中
(freecodeMAN)
给的答案,我又对第三态图C(EaraseBkgrnd)做了return TRUE,但是闪屏仍然存在!
请多多指教!上面的代码一贴出来了,临时改的,比较乱,各位辛苦了
(righthook8)
你的意思我明白,我再后面打了个?,这是我在写程序时,提醒自己的,原来程序中就是直接画长方形,后来想到用双缓冲来解决画长方形防闪烁的方法,就写了这么一句,贴的时候忘了删掉,望勿见怪!请多多指教。学MFC没多久,见笑了!
但有些时候你会调用一些函数, 导致子窗口刷新同时父窗口也会调用EreaseBkgrnd或者OnPaint。
这样你虽然用了双缓冲, 但是父窗口的刷新, 可能导致你子窗口两次OnPaint中间产生间隔, 显示父背景, 而形成闪烁.