当我快速刷新窗口内容的时候会出现严重闪烁的情况,如果才能避免呢?
例如:
unsigned int i=0;
while(i++<30000)
{
//此处在窗口上显示i的值
}
例如:
unsigned int i=0;
while(i++<30000)
{
//此处在窗口上显示i的值
}
解决方案 »
- INI文件大小有没有限制
- 这样的程序怎么改变它的桌面图标
- 谁有VSS下载,请大师们提供个下载的地址?
- 如何使用CMSFlexGrid类中的additem?
- 通过HTTP如何获得服务器文件的信息(尺寸、时间)?要求使用MFC
- 程序怎么和一个CALLBACK函数进行数据通讯?
- (CFile file,fname.txt与程序在同一文件夹中)为什么用file.open("fname.txt",CFile::ModeRead),在集成开发环境中点那红色的感叹号或Ctr
- 属性表的问题,回答一定给分。现在问题升级了,我都快疯了,大家帮帮忙
- 有考过软件设计师的吗
- 如何动态改变对话框的大小
- 请教高手关于自绘菜单的问题
- CSocket错误!!!万分火急-谢谢!!!!
问一下
这么干有意义麽?
2003-01-01(Kang)
1 简单过程描述
在视图(Cview及其子类)每次重绘的过程中,都调用OnDraw( )函数。在调用Invalidate()、InvalidateRect()函数过程后,系统自动调用OnDraw()函数,完成视图的刷新显示。以InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE)为例说明简单过程,调用InvalidateRect()后,系统判断指定的矩形lpRect是否在视图的显示范围(滚动视图显示区域)内,如果在,就调用OnDraw()函数执行重绘,重绘后按照lpRect指针所指向的矩形指定的无效区域进行视图更新。
视图的更新需要一部分时间,所以我们要考虑减小视图每次更新矩形的区域,也就是减小InvalidateRect()中第一个参数lpRect的大小。所以我们应该在需要刷新时,计算刷新矩形的大小,然后调用InvalidateRect()函数。
2 闪屏问题的解决
闪屏问题的解决办法是采用双缓冲技术。即创建与设备DC兼容的位图,在位图中绘制,然后Copy到屏幕上。注意,要重载BOOL CDrawView::OnEraseBkgnd(CDC*)函数,返回TRUE;
即
BOOL CDrawView::OnEraseBkgnd(CDC*)
{
return TRUE;
}
不多叙述。
3 刷新效率
我们最理想的刷新元件的思路就是每次只绘制那些在无效矩形区域内的元件,其余的部分不变。实际的情况是我们在调用OnDraw()函数时,必须遍历所有的元件,然后根据情况选择重绘的元件,将其显示。有两种方法可以选择,一是遍历每个元件的时候判断它是否位于裁减区域内(其对应于无效矩形区域),如在就绘制,否则不进行绘制;第二种方法,思路差不多,是创建一个与裁减矩形同样大小的位图,在位图DC上绘制所有元件,这个在绘制时,超出位图矩形大小的元件就不被绘制,判断元件是否超出位图矩形的工作有系统来做。两种方法效率应该差不多,但第二种方法实现简便,效率相对优于第一种方法。
曾进行过如下测试:
每次无效矩形Crect(0,0,100,100)
for (int k=0; k<100 0000; k++)
{
pDrawDC->Rectangle(100,100,150,150);
}
在无效矩形外,执行1000,000次绘矩形操作,略有延迟。其实,循环体内,只进行的是系统的判断工作,没有绘制。
证明方法可行。
4实现过程的描述
为消除闪屏和充分考虑绘图效率,采用如下方法。
将每次要更新的矩形绘制在位图中,然后将其复制到OnDraw()函数的pDC中;每次执行元件移动,创建等操作时,定义无效矩形,调用InvalidateRect(rect,FALSE)函数。只有当视图ReSize时才全部元件重绘,效率能够得到足够的保证。
重载OnDraw()函数
CDC dc;
CDC* pDrawDC = pDC;
CBitmap bitmap;
CBitmap* pOldBitmap; // only paint the rect that needs repainting
CRect client;
pDC->GetClipBox(client);
CRect rect = client; DocToClient(rect); if (!pDC->IsPrinting())
{
// draw to offscreen bitmap for fast looking repaints
if (dc.CreateCompatibleDC(pDC))
{
if (bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height()))
{
OnPrepareDC(&dc, NULL);
pDrawDC = &dc; // offset origin more because bitmap is just piece of the whole drawing
dc.OffsetViewportOrg(-rect.left, -rect.top);
pOldBitmap = dc.SelectObject(&bitmap);
dc.SetBrushOrg(rect.left % 8, rect.top % 8); // might as well clip to the same rectangle
dc.IntersectClipRect(client);
}
}
} // paint background
CBrush brush;
if (!brush.CreateSolidBrush(pDoc->GetPaperColor()))
return; brush.UnrealizeObject();
pDrawDC->FillRect(client, &brush); if (!pDC->IsPrinting() && m_bGrid)
DrawGrid(pDrawDC); pDoc->Draw(pDrawDC, this); if (pDrawDC != pDC)
{
pDC->SetViewportOrg(0, 0);
pDC->SetWindowOrg(0,0);
pDC->SetMapMode(MM_TEXT);
dc.SetViewportOrg(0, 0);
dc.SetWindowOrg(0,0);
dc.SetMapMode(MM_TEXT);
pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(),
&dc, 0, 0, SRCCOPY);
dc.SelectObject(pOldBitmap);
}