惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
A
About on SuperTechFans
博客园 - Franky
Engineering at Meta
Engineering at Meta
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
B
Blog
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
Stack Overflow Blog
Stack Overflow Blog
博客园 - 叶小钗
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
Last Week in AI
Last Week in AI
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
V
V2EX
G
Google Developers Blog

博客园 - shelvenn's blog

Linux Samba服务器配置 MiniGUI应用程序开发 RTP QOS RTCP (转)H.264 RTP payload 格式 gcc和g++的区别(很详细的描述) RTSP简介 DirectDraw基础篇 DirectShow中常见的RGB/YUV格式(转) #Pragma应用详解 Linux下的实时流媒体编程(RTP,RTCP,RTSP) Linux多线程编程 VC++2005快速构建安全的应用程序 strcpy ,strncpy ,strlcpy(转载) strcpy_s与strcpy安全性的比较(转载) .h和.cpp文件的区别 YUV色彩空间(转自百度百科) C++ PASCAL关键字(转) SkinMagic 进行皮肤设置
窗口刷新时的问题(转)
shelvenn's blog · 2008-02-22 · via 博客园 - shelvenn's blog

1、将Invalidate()替换为InvalidateRect()。  
   
    Invalidate()会导致整个窗口的图象重画,需要的时间比较长,而InvalidateRect()仅仅重画Rect

区域内的内容,所以所需时间会少一些。虫虫以前很懒,经常为一小块区域的重画就调用Invalidate(),

不愿意自己去计算需要重画的Rect,但是事实是,如果你确实需要改善闪烁的情况,计算一个Rect所用的

时间比起重画那些不需要重画的内容所需要的时间要少得多。  
   
  2、禁止系统擦除你的窗口。  
   
    系统在需要重画窗口的时候会帮你用指定的背景色来擦除窗口。可是,也许需要重画的区域也许非

常小。或者,在你重画这些东西之间还要经过大量的计算才能开始。这个时候你可以禁止系统擦掉原来的

图象。直到你已经计算好了所有的数据,自己把那些需要擦掉的部分用背景色覆盖掉(如:dc.FillRect

(rect,&brush);rect是需要擦除的区域,brush是带背景色的刷子),再画上新的图形。要禁止系统擦除

你的窗口,可以重载OnEraseBkgnd()函数,让其直接返回TRUE就可以了。如  
   
  BOOL   CMyWin::OnEraseBkgnd(CDC*   pDC)    
  {  
  return   TRUE;  
  //return   CWnd::OnEraseBkgnd(pDC);//把系统原来的这条语句注释掉。  
  }    
   
    3、有效的进行擦除。  
   
    擦除背景的时候,不要该擦不该擦的地方都擦。比如,你在一个窗口上放了一个很大的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();    
   
    注意:在使用这个方法的时候要同时使用方法二。别忘了,到时候又说虫虫的办法不灵。  
   
    4、使用MemoryDC先在内存里把图画好,再复制到屏幕上。  
   
    这对于一次画图过程很长的情况比较管用。毕竟内存操作比较快,而且复制到屏幕又是一次性的,

至少不会出现可以明显看出一个东东从左画到右的情况。  
   
  void   CMyWin::OnPaint()    
  {  
  CPaintDC   dc1(this);   //   device   context   for   painting  
  dcMemory.CreateCompatibleDC(&dc1);  
  CBitmap   bmp;//这里的Bitmap是必须的,否则当心弄出一个大黑块哦。  
  bmp.CreateCompatibleBitmap(&dc1,rectClient.Width(),rectClient.Height());  
  dcMemory.SelectObject(&bmp);  
   
  //接下来你想怎么画就怎么画吧。  
  //dcMemory.FillRect(rectClient,&brush);    
   
  dc1.BitBlt(0,0,rectClient.Width(),rectClient.Height(),&dcMemory,0,0,SRCCOPY);  
  dcMemory.DeleteDC();  
  //   Do   not   call   CWnd::OnPaint()   for   painting   messages  
  }  
   
   
  导致窗口闪烁的可能性很多:  
   
  1.   不适当的UpdateWindow调用.Windows给paint消息指定比较低的优先级,以防止窗口不必要的重画.

但是,使用API函数UpdateWindow,迫使窗口立即被重画.不适当的UpdateWindow调用导向导致不必要的重画

。  
   
  2.   调用InvalidateRect而不指定更新矩形。API函数InvalidateRect允许用户指定更新矩形,使得重

画只限于需要重画的区域的区域;可以传递一个空指针给InvalidateRect函数来更新整个窗口,但是这样

画图需要更长时间,结果是不必要的闪烁和低速的画图。  
   
  3.   调用InvalidateRect,而将擦除背景参数不适当的设置为真。如果背景不需要重画,你可以将

InvalidateRect函数中擦出背景的参数(系统默认为true)设为false。  
   
  4.   不适当的使用CS_HREDRAW和CS_VREDRAW窗口风格。仅当客户区的大小改变需要重画整个窗口时,

才需要设置这两种窗口风格。如果窗口中的某些元素需要注重放置,这是必要的;但是大多数的窗口不需

要居中排列任何东西,所以没有必要使用这类风格。MFC默认使用的就是这两种风格,所以需要在窗口构

造函数中去掉这两个属性。