窗口显示时闪烁的原因


        当窗口无效时,Windows会给窗口发出WM_ERASEBKGND消息和WM_PAINT消息,而且WM_ERASEBKGND消息先发出一次或者几次,紧接着是WM_PAINT消息。有一个例外:InvalidateRect()函数的调用会使窗口变得无效,并产生WM_ERASEBKGND消息和WM_PAINT消息,而WM_ERASEBKGND是否产生取决于参数bErase。WM_ERASEBKGND消息响应函数为OnEraseBkgnd(), WM_PAINT消息响应函数为OnPaint()。

       窗口重绘时,先调用OnEraseBkGnd()擦除窗口的现有内容,再调用OnPaint绘制新内容

       问题是这样产生的,缺省的OnEraseBkGnd操作使用窗口的缺省背景刷刷新背景(一般情况下是白刷),而你又自己重画背景的话会造成窗口闪动。在OnEraseBkGnd中,如果你不调用原来缺省的OnEraseBkGnd只是重画背景则不会有闪动,而在OnPaint里面,由于它隐含的调用了OnEraseBkGnd,而你又没有处理OnEraseBkGnd 函数,这时就和窗口缺省的背景刷相关了。OnEraseBkGnd不是每次都会被调用的。如果你调用Invalidate的时候参数为TRUE,那么在OnPaint里面隐含调用BeginPaint的时候就产生WM_ERASEBKGND消息,如果参数是FALSE,则不会重刷背景。 所以解决闪动方法有三个:
1.用OnEraseBkGnd实现,不要调用原来的OnEraseBkGnd函数. 
2.用OnPaint实现,同时重载OnEraseBkGnd,其中直接返回. 
3.用OnPaint实现,创建窗口时设置背景刷为空 

         在MFC中 任何一个window组件的绘图 都是放在OnEraseBkGnd()OnPaint这两个member function中

在设定上 OnEraseBkgnd()是用来画底图的 而OnPaint()是用来画主要对象的

举例说明 一个按钮是灰色的上面还有文字
则OnEraseBkgnd()所做的事就是把按钮画成灰色

而OnPaint()所做的事就是画上文字
既然这两个member function都是用来画出组件的
那为何还要分OnPaint() 与 OnEraseBkgnd() 呢
其实OnPaint() 与 OnEraseBkgnd() 特性是有差的:

1.         OnEraseBkgnd()的要求是快速 在里面的绘图程序最好是不要太耗时间因为每当window组件有任何小变动 都会马上呼叫OnEraseBkgnd()

2.         OnPaint() 是只有在程序有空闲的时候才会被呼叫

3.         OnEraseBkgnd() 是在 OnPaint() 之前呼叫的

所以 OnPaint()被呼叫一次之前 可能会呼叫OnEraseBkgnd()好几次

如果我们是一个在做图形化使用者接口的人常会需要把一张美美的图片设为我们dialog的底图把绘图的程序代码放在OnPaint() 之中 可能会常碰到一些问题比方说拖曳一个窗口在我们做的dialog上面一直移动 则dialog会变成灰色 直到动作停止才恢复这是因为每次需要重绘的时候 程序都会马上呼叫OnEraseBkgnd() OnEraseBkgnd()就把dialog画成灰色而只有动作停止之后 程序才会呼叫OnPaint() 这时才会把我们要画的底图贴上去这个问题的解法 比较差点的方法是把OnEraseBkgnd() 改写成不做事的function如下所示:

BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)

{
   return TRUE;
}
以上本来是会呼叫CDialog::OnEraseBkgnd() 但是如果我们不呼叫的话程序便不会画上灰色的底色了比较好的做法是直接将绘图的程序从OnPaint()移到OnEraseBkgnd()来做如下所示:

// m_bmpBKGND 為一CBitmap物件且事先早已載入我們的底圖
// 底圖的大小與我們的視窗client大小一致
BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
   CRect rc;
   GetUpdateRect(&rc);
 

   CDC srcDC;
   srcDC.CreateCompatibleDC(pDC);
   srcDC.SelectObject(m_bmpBKGND);

   pDC->BitBlt(rc.left,rc.top,rc.GetWidth(),

   rc.GetHeight(),&srcDC,rc.left,rc.top,SRCCOPY);

   return TRUE;
}
特別要注意的是取得重畫大小是使用GetUpdateRect() 而不是GetClientRect()如果使用GetClientRect() 會把不該重畫的地方重畫



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
包含文件说明: 1. SolveFlashingAndRedrawv1.0.5 纯净版 无闪烁MFC应用框架,实际使用把此工程改名成你要建立的项目名称,然后开始开发即可。你熟悉MFC的话研究这个框架的半个小应该就明白并熟练运用了。 2.SolveFlashingAndRedrawv1.0.5 demo版 利用SolveFlashingAndRedrawv1.0.4框架写的一个示例小程序,主要展示框架要实现的优点特性。 3.VCRn 修改vc工程名工具 ___作者 田彬.exe 用网上找到的一个MFC改工程名称的小工具,很实用。如果你想使用本框架就可以用它来改成你想要的工程名了。 4. 未使用本框架的类似功能简化程序 没有使用框架的程序,实现的功能和Demo类似。但是运行之后改变窗口大小等,会发现图形闪烁很厉害! 5. SolveFlashingAndRedrawv1.0.5 demo版 运行截图.jpg 6. ReadMe.txt 说明文件。 补充说明: 工程使用vc6.0开发,如果你用vc6.0双击.dsw文件无法打开,请先打开vc6.0然后把.dsw拖动到vc上面。 如果这种方法还是无法打开,你新建一个vc6.0 mfc sdi程序,把示例中框架拷贝到这个新工程中,运行即可,代码量不是太多。 框架说明: /****************************************************** SolveFlashingAndRedraw框架说明 ******************************************************/ /** 项目名称: demo框架 版本号: v1.0.5 第一作者: Jef 地址: 中国/江苏 日期: 20100724 电子邮箱: dungeonsnd@126.com 版权: 1.您可以修改及免费使用本程序。 2.修改之后附上您的个人信息发送到上面的作者邮箱,作者负责在全面测试后发布您修改后的新版本。 3.您使用本程序而导致任何伤害以及经济损失,由过错方依法承担所有责任,一概与第一作者及合作单位无关。 4.如果您使用本程序则表示您已经同意此版本协议!否则请勿使用! 项目功能: SolveFlashingAndRedraw框架是MFC解决窗口保存及重绘闪烁问题的一种比较好的方案(Win32解决方法类似)。 版本历史: v1.0.1 20091126 第一版本 v1.0.2 20091212 第二版本 1. 修改了部分变量的名字使其更符合其意义 2. 增加为两个工程,一是带demo例子的,另一是不带demo的纯净版. 3. 修改了其中一个错误. 如 CreateCompatibleDC之后没有调用DeleteDC等. v1.0.3 对v1.0.2进行了整理 v1.0.4 20100416 在v1.0.3的基础上进行整理,并增加了裁剪区,提高了绘图效率! v1.0.5 20100724 1. 添加了一个工具类CMemBmpDc,帮助产生一个内存DC,并把指定的内存位图选进去。方便绘图。 2. 演示了在适当机如何高效画图,见Demo版的DrawSinwave(bool bDrawOnScreen)函数。 演示了用两种方法来绘图, 方法1. 直接绘图到屏幕上, 同绘图到内存位图上,内存位图不会立即贴到屏幕上减少了内存拷贝的间,提高了效率, 将来窗口失效OnPait贴图到屏幕上. 这种方法的优点减小了不必要的内存拷贝,缺点当绘图内存复杂并且非常耗可能会导致闪烁。 故适用于像本Demo的这样绘图(本例函数只绘制一小段直线)。 方法2. 绘制到内存位图上后把应该重绘的这一小块设成裁剪区,然后立即OnPait重绘这个裁剪区。 运行步骤: 直接运行demo里面的程序,在窗口上任意拖拉鼠标画线,然后点击菜单栏的几个示范菜单项,然后移动窗口、 改变窗口大小、最大最小化窗口、用其它窗口覆盖此窗口、鼠标放到任务栏。。。 以上种种操作观察窗口内的图像变化。可以发现窗口内图像几乎看不到闪烁,而且窗口的元素已经保存下来重绘任然可以看到图像。 如何使用: 进行项目开发,可以先建立项目,然后把本解决方案框架拷贝到新建项目中即可。 也可以自己根据需要修改纯净版。 其它: 友情提示,小心 View类头文件及View类的实现文件中有说明,使用别把它弄到你实际项目里哦! 进行大量复杂的图形的输出,而且对效率要求特别高要考虑适当修改此框架(如增加裁剪区)后再使用哦。 关于如何在此框架的基础上提高绘图效率可以参阅下面的文章 如何提高绘图的效率 文章摘录 http://hi.baidu.com/new8sun/blog/item/68ccba8a80c3aadafc1f1079.html MFC双缓冲解决图象闪烁 2009-06-13 23:03 显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案。 MFC的绘图效率的确不高但也不差,而且它的绘图函数使用非常简单,只要使用方法得当,再加上一些技巧,用MFC可以得到效率很高的绘图程序。
您好!对于 NativeWindow 出现闪烁的问题,可能有多种原因导致。以下是一些可能的解决方法: 1. 双缓冲(Double buffering):使用双缓冲技术可以减少闪烁。通过在内存中绘制图像,然后一次性将其绘制到窗口上,可以避免直接在窗口上进行绘制造成的闪烁。您可以在绘制使用双缓冲技术来解决闪烁问题。 2. 减少重绘频率:如果您的程序频繁地重绘窗口,可能会导致闪烁。尝试减少重绘的频率,只在必要的情况下进行重绘,可以减少闪烁现象。 3. 使用硬件加速:某些图形库和框架提供硬件加速功能,可以提高绘图性能并减少闪烁。您可以尝试使用支持硬件加速的库或框架来进行绘图操作。 4. 检查窗口属性:确保窗口的属性正确设置,如背景色、透明度等。不正确的窗口属性设置可能导致闪烁问题。 5. 避免频繁改变窗口尺寸:如果您频繁地改变窗口的尺寸,可能会导致闪烁。尽量避免频繁改变窗口大小,或者在改变窗口尺寸采取一些优化措施,以减少闪烁。 6. 更新显卡驱动程序:确保您的显卡驱动程序是最新的,过的驱动程序可能会导致显示问题。 这些是一些常见的解决方法,您可以根据具体情况尝试其中的一些方法来解决闪烁问题。如果问题仍然存在,请提供更多的细节和代码示例,以便更好地帮助您解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值