请问有谁知道防止窗口闪烁
碰到过这种情况,当想重画某个窗口的时候,或你需要每隔一段时间要进行重画窗口,窗口会不停的闪烁。 问题点数:100、回复次数:14Top
1 楼JaeBear(熊)回复于 2005-01-28 09:45:44 得分 0
窗口闪烁大概是因为调用了Invalidate(),如果只是想要重画某个控件的窗口,只需要“控件.Invalidate()”,这样就只更新了控件窗体,而整个窗口不会闪烁。
如果是要重画整个窗口又不要闪烁,呵呵…………俺也不大清楚,请高手指教Top
2 楼Stone2005(石头啦)回复于 2005-01-28 09:48:26 得分 0
因为Invalidate()会导致整个窗口的图象重画,需要的时间比较长,而InvalidateRect()仅仅重画Rect区域内的内容,所需时间会少一些。所以替换之后在很大程度上会减少闪烁。如果你确实需要改善闪烁的情况,计算一个Rect所用的时间比起重画那些不需要重画的内容所需要的时间要少得多。Top
3 楼Stone2005(石头啦)回复于 2005-01-28 09:52:26 得分 0
这个试试看看
不要让系统擦除你的窗口。
系统在需要重画窗口的时候会帮你用指定的背景色来擦除窗口。可是,也许需要重画的区域也许非常小。或者,在你重画这些东西之间还要经过大量的计算才能开始。这个时候你可以禁止系统擦掉原来的图象。直到你已经计算好了所有的数据,自己把那些需要擦掉的部分用背景色覆盖掉(如:dc.FillRect(rect,&brush);rect是需要擦除的区域,brush是带背景色的刷子),再画上新的图形。要禁止系统擦除你的窗口,可以重载OnEraseBkgnd()函数,让其直接返回TRUE就可以了。如
BOOL CMyWin::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
//return CWnd::OnEraseBkgnd(pDC);//把系统原来的这条语句注释掉。
}Top
4 楼clovexmu(Seek Love,C language Love,S.H.E Love)回复于 2005-01-28 10:16:50 得分 0
又是石头?Top
5 楼DentistryDoctor(Data Recovery -- http://www.powerdatarecovery.com)回复于 2005-01-28 10:21:42 得分 5
Invalidate(FALSE)/InvalidateRect(rect,FALSE);
采用双缓冲绘图。Top
6 楼handwolf(青松崖)回复于 2005-01-28 10:21:45 得分 0
调用Invalidate()是重绘整个窗口,
建议调用调用了InvalidateRect(),参数是一个矩形,这样重绘的是这个参数中矩形所对应的窗口部分!
如果你每次只是改变一部分,那么这个方法是可行的1Top
7 楼Stone2005(石头啦)回复于 2005-01-28 10:45:12 得分 0
------------->clovexmu 你好啊,你认识我吗?Top
8 楼fly950223(彪)回复于 2005-01-28 10:45:50 得分 10
一般的做法是:
如果是控件闪烁,可以重载此控件类的
OnEraseBkgnd(CDC *pDC){return true};
并在OnPaint()函数中使用内存DC.
如果是整个界面闪烁,并且更新界面的过程比较长,可以先锁定窗口,等数据更新完后再一次性的
刷新整个窗口,当然这个视类也可以重载上面的两个函数,方法一样Top
9 楼Stone2005(石头啦)回复于 2005-01-28 10:46:15 得分 70
擦除背景的时候,不要该擦不该擦的地方都擦。比如,你在一个窗口上放了一个很大的Edit框,几乎占了整个窗口,那么你频繁的擦除整个窗口背景将导致Edit不停重画形成剧烈的闪烁。事实上你可以CRgn创建一个需要擦除的区域,只擦除这一部分。如
GetClientRect(rectClient);
rgn1.CreateRectRgnIndirect(rectClient);
rgn2.CreateRectRgnIndirect(m_rectEdit);
if(rgn1.CombineRgn(&rgn1,&rgn2,RGN_XOR) == ERROR)//处理后的rgn1只包括了Edit框之外的客户区域,这样,Edit将不会被我的背景覆盖而导致重画。
{
ASSERT(FALSE);
return ;
}
brush.CreateSolidBrush(m_clrBackgnd);
pDC->FillRgn(&rgn1,&brush);
brush.DeleteObject();Top
10 楼orbit(走了走了)回复于 2005-01-28 10:48:26 得分 0
在重画窗口时(OnPaint或OnDraw for MFC)中使用兼容的内存DC可以避免或减轻闪烁Top
11 楼Stone2005(石头啦)回复于 2005-01-28 10:54:24 得分 0
兼容的内存DC无法避免闪烁Top
12 楼Jacky1206(胖胖,其实我不胖)回复于 2005-01-28 11:00:12 得分 0
Stone2005(石头啦) 说的 n 正确Top
13 楼Stone2005(石头啦)回复于 2005-01-28 11:02:42 得分 0
STONE------------> MONEY LOVE SOURCE LOVE GIRL LOVE AND WORLD LOVE ,哈哈哈哈Top
14 楼w8u(晌马)回复于 2005-01-28 11:28:02 得分 15
关键技术:
1,局部更新,参考:GetClipBox,用该函数得到的矩形区域,与数据是否落在该区域比较来决定是否需要重画。
2,内存缓冲DC。现在内存里画图,然后再一次性的考到实际DC上。
3,
BOOL CMyTestView::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
return TRUE;
return CScrollView::OnEraseBkgnd(pDC);
}
这是我的一个函数:
void CMyTestView::OnDraw(CDC* pDC)
{
CMyTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
Lines& lines = pDoc->lines;
int nLine=0;
TCHAR* szText = NULL;
CDC dc;
CBitmap bitmap;
CBitmap* pOldBitmap;
CRect rectClipBox;
pDC->GetClipBox(&rectClipBox);
//TRACE(TEXT("\n\nClip Box = %d,%d,%d,%d"),rectClipBox.left,rectClipBox.top,rectClipBox.right,rectClipBox.bottom);
CRect rectLine,rectTmp,rectLines(0,0,0,0),rectClient;
GetClientRect(&rectClient);
rectLine = rectClient;
rectLine.bottom =0;
rectLine.top =0;
int nWidth = rectClipBox.Width();
int nHeight = rectClipBox.Height();
if(dc.CreateCompatibleDC(pDC))//创建一个与pDC兼容的内存设备环境
{
if(bitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight))//创建一与pDC兼容的位图,大小为整个Clip Box
{
OnPrepareDC(&dc,NULL);//使dc与pDC具有同样的映射关系
pOldBitmap=dc.SelectObject(&bitmap);//将位图选入内存环境
//dc.SelectClipRgn(NULL);//使dc的整个客户区都成无效区
//dc.FillRect(&client, GetStockObject(WHITE_BRUSH));
dc.FillSolidRect(0,0, nWidth , nHeight,RGB(255,255,255) );
for( Lines::iterator it = lines.begin();it != lines.end() ; it ++)
{
rectLine.top= (nLine)*16 ;
rectLine.bottom=(nLine + 1) * 16;
//TRACE(TEXT("\n %d:Line Rect = %d,%d,%d,%d"),nLine,rcLine.left,rcLine.top,rcLine.right,rcLine.bottom);
if (rectTmp.IntersectRect(rectLine,rectClipBox) )
{
//TRACE(TEXT("\n%d----------"),nLine);
//dc.IntersectClipRect(rcLine); //再"与上"检取的无效区,使
//内存环境与pDC检取的无效区相等
//rectLines.IntersectRect(rcLines,rcLine);
szText = *it;
dc.SetTextColor(RGB(255,(nLine % 2 ? 0 : 125) ,244));
dc.SelectObject(&m_font);
dc.SetBkMode( TRANSPARENT );
dc.TextOut(0, ( nLine*16 - rectClipBox.top ),szText);
}
nLine ++;
}
pDC->BitBlt( rectClipBox.left,rectClipBox.top,rectClipBox.Width(),rectClipBox.Height(),
&dc,0,0,SRCCOPY);//将内存裁减区的位图
//拷贝到窗口裁减区
dc.SelectObject(pOldBitmap);
dc.DeleteDC();
}
}
}
Top




