解决MFC绘图过程中的闪烁
+MFC+GDI双缓冲避免图形闪烁

// TODO: Add your specialized creation code here SetTimer(1,10,NULL); return 0; } 利用定时器直接进行 10 毫秒的屏幕刷新,这样效果会出现不停的闪烁的情况. 解决方法利用双缓冲,首先触发 WM_ERASEBKGND,然后修改返回 TRUE; 定义变量: CBitmap *m_pBitmapOldBackground ; CBitmap m_bitmapBackground ; CDC m_dcBackground; //绘制背景 if(m_dcBackground.GetSafeHdc()== NULL|| (m_bitmapBackground.m_h Object == NULL)) {
MemDC.CreateCompatibleDC(NULL); //这时还不能绘图,因为没有地方画 ^_^ //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的 大小 MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight); //将位图选入到内存显示设备中 //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上 CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap); //先用背景色将位图清除干净,这里我用的是白色作为背景 //你也可以用自己应该用的颜色 MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255)); //绘图 MemDC.MoveTo(……); MemDC.LineTo(……);
} 说到这里可能又有人要说了 , 为什么一个简单图形看起来没有复杂图形那么闪呢? 这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要闪得厉 害一些,但是闪烁频率要低。 那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了,闪烁 是什么?闪烁就是反差,反差越大,闪烁越厉害。因为动画的连续两个帧之间的 差异很小所以看起来不闪 。 如果不信 , 可以在动画的每一帧中间加一张纯白的帧 , 不闪才怪呢。 2、如何避免闪烁 在知道图形显示闪烁的原因之后,对症下药就好办了。首先当然是去掉 MFC 提 供的背景绘制过程了。实现的方法很多, * 可以在窗口形成时给窗口的注册类的背景刷付 NULL * 也可以在形成以后修改背景 static CBrush brush(RGB(255,0,0)); SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRU SH)brush); * 要简单也可以重载 OnEraseBkgnd(CDC* pDC)直接返回 TRUE. 这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,变 得一团乱。怎么办?这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图 形进行显示以外,在内存中也有图形在绘制。我们可以把要显示的图形先在内存 中绘制好 , 然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去 (这个过程非常快,因为是非常规整的内存拷贝)。这样在内存中绘图时,随便 用什么反差大的背景色进行清除都不会闪,因为看不见。当贴到屏幕上时,因为 内存中最终的图形与屏幕显示图形差别很小 (如果没有运动 , 当然就没有差别) , 这样看起来就不会闪。 3、如何实现双缓冲 首先给出实现的程序,然后再解释,同样是在 OnDraw(CDC *pDC)中: CDC MemDC; //首先定义一个显示设备对象 CBitmap MemBitmap;//定义一个位图对象 //随后建立与屏幕显示兼容的内存显示设备
C#Picturebox控件上画图闪烁问题的解决方案

} gg.Dispose();
//将要绘制的内容绘制到dc上
g.DrawImage(b, 0, 0); gg.Dispose(); }
Bitmap b = new Bitmap(this.Width, this.Height); Graphics dc = Graphics.FromImage((System.Drawing.Image)b);
//将要绘制的内容绘制到dc上
g.DrawImage(b, 0, 0); dc.Dispose();
Bitmap b = new Bitmap(this.Width, this.Height); Graphics gg = Graphics.FromImage((System.Drawing.Image)b); Pen bi = new Pen(Color.Blue, 2); for (int i = 0; i < 1; i++) {
请求出错错误代码400请尝试刷新页面重试
C#Picturebox控 件 上 画 图 闪 烁 问 题 的 解 决 方 案
引用:
Graphics g = e.Graphics;
//注意,这里千万不可用Graphics g = this.CreateGraphics() 获得绘图变量。否则闪烁将非常厉害。
使用实例:
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
Graphics g = e.Graphics;
经验总结之防止窗口闪烁的方法

VC无闪烁刷屏技术的实现---经验总结之防止窗口闪烁的方法也许我们都碰到过这种情况,当你想重画某个窗口的时候,或你需要每隔一段时间要进行重画窗口,窗口会不停的闪烁。
那么如何消除闪烁呢?借鉴了别人的经验,自己也总结一下,现将总结的几种方法介绍一下,供大家参考。
1、将Invalidate()替换为InvalidateRect()。
因为Invalidate()会导致整个窗口的图象重画,需要的时间比较长,而InvalidateRect()仅仅重画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(bineRgn(&rgn1,&rgn2,RGN_XOR) == ERROR)//处理后的rgn1只包括了Edit框之外的客户区域,这样,Edit将不会被我的背景覆盖而导致重画。
于双缓冲技术的GDI无闪烁绘图

Abstract: Graphics flickering is an intractable common problem when programming Windows forms applications by using GDI + . On the basis of profound analysis on the model of form redrawing, the essentials of graphics flickering were explained in this paper. Two flickerfree GDI + drawing methods were proposed based on double buffering built in the . NET framework. To take analog clock as an example, it is shown that these two methods are very easytouse and effective. Key words: double buffering; flickerfree drawing; graphics flickering; GDI + ; . NET framework; analog clock
基于双缓冲技术的 GDI + 无闪烁绘图
江建国 ,温少营,张瑞楠
( 辽宁师范大学 数学学院, 辽宁 大连 116029 ) ( * 通信作者电子邮箱 jjgbox@ sina. com)
*
要: 图形闪烁是使用 GDI + 编写 Windows 窗体应用程序时经 常 遇 到的 一 个 问题。 在 深 入 分析 窗 体重 绘 模型 阐述了图形闪烁的本质原因。利用. NET框架 中 内 置 的 双 缓 冲 技术, 提出了 两 种 GDI + 无 闪烁 绘 图方 法。 以 基础上, 模拟时钟程序为例, 说明了这两种方法都非常简便且有效。 关键词: 双缓冲; 无闪烁绘图; 图形闪烁; GDபைடு நூலகம் + ; . NET框架; 模拟时钟 中图分类号: TP391. 41 文献标志码: A
[C#开发小技巧]解决WinForm控件TabControl闪烁问题
![[C#开发小技巧]解决WinForm控件TabControl闪烁问题](https://img.taocdn.com/s3/m/2a633b46777f5acfa1c7aa00b52acfc789eb9f2c.png)
[C#开发⼩技巧]解决WinForm控件TabControl闪烁问题在⽤C#开发WinForm程序时,常发现TabControl出现严重的闪烁问题,这主要是由于TabControl控件在实现时会绘制默认的窗⼝背景。
其实以下⼀段简单的代码可以有效的缓解该问题的发⽣。
这就是技巧的作⽤,不需要理解太多的知识,但需要多多积累,就能做到事半功倍的效果。
1using System;2using System.Collections.Generic;3using System.Text;4using System.Windows.Forms;5namespace WfGUI.Forms6{7///<summary>8///不会闪烁的TabContriol9///</summary>10public class NoFlashTabControl : TabControl11 {12///<summary>13///构造函数,设置控件风格14///</summary>15public NewTabControl()16 {17 SetStyle18 ( ControlStyles.AllPaintingInWmPaint //全部在窗⼝绘制消息中绘图19 | ControlStyles.OptimizedDoubleBuffer //使⽤双缓冲20 , true);21 }22///<summary>23///设置控件窗⼝创建参数的扩展风格24///</summary>25protected override CreateParams CreateParams26 {27get28 {29 CreateParams cp = base.CreateParams;30 cp.ExStyle |= 0 x02000000;31return cp;32 }33 }34 }35 }标签: C#, TabControl, WinForm, 控件, 程序开发。
VC窗口闪烁问题的解决

一般的windows 复杂的界面需要使用多层窗口而且要用贴图来美化,所以不可避免在窗口移动或者改变大小的时候出现闪烁。
先来谈谈闪烁产生的原因原因一:如果熟悉显卡原理的话,调用GDI函数向屏幕输出的时候并不是立刻就显示在屏幕上只是写到了显存里,而显卡每隔一段时间把显存的内容输出到屏幕上,这就是刷新周期。
一般显卡的刷新周期是1/80秒左右,具体数字可以自己设置的。
这样问题就来了,一般画图都是先画背景色,然后再把内容画上去,如果这两次操作不在同一个刷新周期内完成,那么给人的视觉感受就是,先看到只有背景色的图像,然后看到画上内容的图像,这样就会感觉闪烁了。
解决方法:尽量快的输出图像,使输出在一个刷新周期内完成,如果输出内容很多比较慢,那么采用内存缓冲的方法,先把要输出的内容在内存准备好,然后一次输出到显存。
要知道一次API 调用一般可以在一个刷新周期内完成。
对于GDI,用创建内存DC的方法就可以了原因二:复杂的界面有多层窗口组成,当windows在窗口改变大小的时候是先重画父窗口,然后重画子窗口,子父窗口重画的过程一般无法在一个刷新周期内完成,所以会呈现闪烁。
我们知道父窗口上被子窗口挡住的部分其实没必要重画的解决方法:给窗口加个风格WS_CLIPCHILDREN ,这样父窗口上被子窗口挡住的部分就不会重画了。
如果同级窗口之间有重叠,那么需要再加上WS_CLIPSIBLINGS 风格原因三:有时候需要在窗口上使用一些控件,比如IE,当你的窗口改变大小的时候IE会闪烁,即使你有了WS_CLIPCHILDREN也没用。
原因在于窗口的类风格有CS_HREDRAW 或者CS_VREDRAW,这两个风格表示窗口在宽度或者高度变化的时候重画,但是这样就会引起IE闪烁解决方法:注册窗口类的时候不要使用这两个风格,如果窗口需要在改变大小的时候重画,那么可以在WM_SIZE的时候调用RedrawWindow。
原因四:界面上窗口很多,而且改变大小时很多窗口都要移动和改变大小,如果使用MoveWindow 或者SetWindowPos两个API来改变窗口的大小和位置,由于他们是等待窗口重画完成后才返回,所以过程很慢,这样视觉效果就可能会闪烁。
一种基于自定义剪切区集合的MFC程序GDI绘图优化方法-浙江中控技术股份有限公司

一种基于自定义剪切区集合的MFC程序GDI绘图优化方法罗幸明,徐伟强浙江中控技术股份有限公司,浙江杭州,310053摘要:传统MFC程序GDI绘图仅考虑屏幕刷新闪烁的优化,而对于绘图内容本身的优化考虑有限。
常规应用下,GDI绘图本身确实不会成为程序的性能瓶颈,但在高分辨率、复杂画面的绘制显示时,这个问题就不得不考虑了。
通常我们会使用系统剪切区进行优化控制,但是实际应用发现当分辨率或者画面复杂度大于一定程度后,该优化的性能提升有限。
鉴于此,本文提出了一种简单可行的基于自定义剪切区集合判断的MFC程序GDI绘图优化方法,可以有效解决高分辨率、复杂画面的GDI绘图性能问题。
关键词:自定义剪切区、MFC、GDI、绘图One Optimizing Design Based On Custom Clipping Region Sets Of MFC Programs Drawing With GDILuo Xingming,Xu WeiqiangZhejiang SUPCON Co.,Ltd, Hangzhou, Zhejiang, 310053Abstract:When drawing with GDI of traditional MFC programs,the most considering things is the screen flashing problems but not drawing itself.Normally drawing performance will not be the choke point,but it really will be when screen resolution is high enough or graphics is complex enough.It is usual to resolve this problem by using system clipping region,but after some industial practice we found that the benefits from this optimizing is limited.Based on this situation,this paper presents a simple effective and practical optimizing design based on custom clipping region sets which can effectivly improve drawing performance of complex graphics in industrial field. Keyword:Custom Clipping Region Sets, MFC, GDI, Drawing基金项目“石化、轨道交通行业分布式综合监控系统(SCADA)研发及应用示范”资助1.GDI概述GDI(Graphics Device Interface)是Windows操作系统的传统图形子系统,负责与设备无关的图形绘制,Win32 API为应用程序提供了丰富的绘图函数和功能,而MFC又对他们进行了C++类的封装。
双缓冲

双缓冲图形刷新技术顾名思义是采用双缓存实现的。传统的绘图方式实际上是一种单缓冲。在windows中每一种设备都在内存中有一个设备描述表与其对应,这个设备描述表实际上就是一个内存缓冲区。传统的绘图中我们是将图形绘制在设备描述表缓冲区中,然后由gdi自动的将设备描述表中的图像拷贝到显存中进行显示。这样一个自动的拷贝过程屏蔽了传统的绘图方式是单缓冲的实质,使我们感觉到我们是在直接操纵显存一样。双缓冲图形刷新技术在内存中有两片缓存,除了设备描述表以外还有一个需要手动建立的与设备描述表缓冲区(前端缓冲区)相兼容的后备缓冲区。绘图过程中,首先将图形绘制在后备缓冲区中,然后在手动的将后备缓冲区中的图像拷贝到前端缓冲区中,再由gdi自动将前端缓冲区中的图像拷贝到显存完成图形的显示过程。
//先用背景色将位图清除干净,这里我用的是白色作为背景
//你也可以用自己应该用的颜色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
//绘图
MemDC.MoveTo(……);
MemDC.LineTo(……);
//将后备缓冲区中的图形拷贝到前端缓冲区
1、编写一个刷新速度很慢的应用程序,可以设计为通过点击鼠标来进行屏幕刷新。通过该试验可以发现即使屏幕的刷新速度很慢,但是在每次刷新的时候仍然存在屏幕的问题,只是闪烁不是很明显。
2、编写一个刷新速度很快的应用程序,并在程序中应用双缓冲图形刷新技术。通过该试验可以发现虽然屏幕刷新速度很快,但是采用了双缓冲图新刷新技术以后,屏幕不存在闪烁。
CBitmap MemBitmap;
//建立与屏幕设备描述表(前端缓冲区)兼容的内存设备描述表句柄(后备缓冲区)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
如何解决绘图过程中的闪烁在VC中进行绘图过程处理时,如果图形刷新很快,经常出现图形闪烁的现象。
利用先在内存绘制,然后拷贝到屏幕的办法可以消除屏幕闪烁,具体的方法是先在内存中创建一个与设备兼容的内存设备上下文,也就是开辟一快内存区来作为显示区域,然后在这个内存区进行绘制图形。
在绘制完成后利用BitBlt函数把内存的图形直接拷贝到屏幕上即可。
具体的代码实现为:(1)创建内存区域CDC* pMem=new CDC;CBitmap* pBmp=new CBitmap;CBitmap* pOldBmp;CDC* pDC=GetDC();CRect rectTemp;为绘图区域pMem->CreateCompatibleDC(pDC);pBmp->CreateCompatibleBitmap(pDC, rectTemp.Width(), rectTemp.Height());pOldBmp=pMem->SelectObject(pBmp);(2)进行图形绘制pMem->LineTo(...); 进行绘图处理(3)拷贝到屏幕pDC->BitBlt(rectTemp.left,rectTemp.top,rectTemp.Width(),rectTemp.Height(),pMem,0,0,SRCCO PY);pMem->SelectObject(pOldBmp);pBmp->DeleteObject() ;pMem->DeleteDC();====================================================================== ==========================双缓存机制解决VC++绘图时的闪烁问题显示图形如何避免闪烁,如何提高显示效率是问得比较多的问题。
而且多数人认为MFC的绘图函数效率很低,总是想寻求其它的解决方案。
MFC的绘图效率的确不高但也不差,而且它的绘图函数使用非常简单,只要使用方法得当,再加上一些技巧,用MFC可以得到效率很高的绘图程序。
我想就我长期(呵呵当然也只有2年多)使用MFC绘图的经验谈谈我的一些观点。
1、显示的图形为什么会闪烁?我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。
当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。
如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。
当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。
有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的,其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。
例如在OnDraw(CDC *pDC)中这样写:pDC->MoveTo(0,0);pDC->LineTo(100,100);这个绘图过程应该是非常简单、非常快了吧,但是拉动窗口变化时还是会看见闪烁。
其实从道理上讲,画图的过程越复杂越慢闪烁应该越少,因为绘图用的时间与用背景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。
比如:清楚屏幕时间为1s绘图时间也是为1s,这样在10s内的连续重画中就要闪烁5次;如果清楚屏幕时间为1s不变,而绘图时间为9s,这样10s内的连续重画只会闪烁一次。
这个也可以试验,在OnDraw(CDC *pDC)中这样写:for(int i=0;i<100000;i++){pDC->MoveTo(0,i);pDC->LineTo(1000,i);}呵呵,程序有点变态,但是能说明问题。
说到这里可能又有人要说了,为什么一个简单图形看起来没有复杂图形那么闪呢?这是因为复杂图形占的面积大,重画时造成的反差比较大,所以感觉上要闪得厉害一些,但是闪烁频率要低。
那为什么动画的重画频率高,而看起来却不闪?这里,我就要再次强调了,闪烁是什么?闪烁就是反差,反差越大,闪烁越厉害。
因为动画的连续两个帧之间的差异很小所以看起来不闪。
如果不信,可以在动画的每一帧中间加一张纯白的帧,不闪才怪呢。
2、如何避免闪烁在知道图形显示闪烁的原因之后,对症下药就好办了。
首先当然是去掉MFC提供的背景绘制过程了。
实现的方法很多,* 可以在窗口形成时给窗口的注册类的背景刷付NULL* 也可以在形成以后修改背景static CBrush brush(RGB(255,0,0));SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);* 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE这样背景没有了,结果图形显示的确不闪了,但是显示也象前面所说的一样,变得一团乱。
怎么办?这就要用到双缓存的方法了。
双缓冲就是除了在屏幕上有图形进行显示以外,在内存中也有图形在绘制。
我们可以把要显示的图形先在内存中绘制好,然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去(这个过程非常快,因为是非常规整的内存拷贝)。
这样在内存中绘图时,随便用什么反差大的背景色进行清除都不会闪,因为看不见。
当贴到屏幕上时,因为内存中最终的图形与屏幕显示图形差别很小(如果没有运动,当然就没有差别),这样看起来就不会闪。
3、如何实现双缓冲首先给出实现的程序,然后再解释,同样是在OnDraw(CDC *pDC)中:CDC MemDC; //首先定义一个显示设备对象CBitmap MemBitmap;//定义一个位图对象//随后建立与屏幕显示兼容的内存显示设备MemDC.CreateCompatibleDC(NULL);//这时还不能绘图,因为没有地方画 ^_^//下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);//将位图选入到内存显示设备中//只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);//先用背景色将位图清除干净,这里我用的是白色作为背景//你也可以用自己应该用的颜色MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));//绘图MemDC.MoveTo(……);MemDC.LineTo(……);//将内存中的图拷贝到屏幕上进行显示pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);//绘图完成后的清理MemBitmap.DeleteObject();MemDC.DeleteDC();上面的注释应该很详尽了,废话就不多说了。
4、如何提高绘图的效率我主要做的是电力系统的网络图形的CAD软件,在一个窗口中往往要显示成千上万个电力元件,而每个元件又是由点、线、圆等基本图形构成。
如果真要在一次重绘过程重画这么多元件,可想而知这个过程是非常漫长的。
如果加上了图形的浏览功能,鼠标拖动图形滚动时需要进行大量的重绘,速度会慢得让用户将无法忍受。
怎么办?只有再研究研究MFC 的绘图过程了。
实际上,在OnDraw(CDC *pDC)中绘制的图并不是所有都显示了的,例如:你在OnDraw中画了两个矩形,在一次重绘中虽然两个矩形的绘制函数都有执行,但是很有可能只有一个显示了,这是因为MFC本身为了提高重绘的效率设置了裁剪区。
裁剪区的作用就是:只有在这个区内的绘图过程才会真正有效,在区外的是无效的,即使在区外执行了绘图函数也是不会显示的。
因为多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生,改变的区域并不是整个图形而只有一小部分,这一部分需要改变的就是pDC 中的裁剪区了。
因为显示(往内存或者显存都叫显示)比绘图过程的计算要费时得多,有了裁剪区后显示的就只是应该显示的部分,大大提高了显示效率。
但是这个裁剪区是MFC设置的,它已经为我们提高了显示效率,在进行复杂图形的绘制时如何进一步提高效率呢?那就只有去掉在裁剪区外的绘图过程了。
可以先用 pDC->GetClipBox()得到裁剪区,然后在绘图时判断你的图形是否在这个区内,如果在就画,不在就不画。
如果你的绘图过程不复杂,这样做可能对你的绘图效率不会有提高。
====================================================================== ================================================================================================= =================================================VC++大数据量绘图时无闪烁刷屏技术实现引言当我们需要在用户区显示一些图形时,先把图形在客户区画上,虽然已经画好但此时我们还无法看到,还要通过程序主动地刷新用户区,强制Windows发送一条WM_PAINT消息,这将引发视类OnDraw函数简单地将所有的图形对象重画,这样才完成了图形的显示工作,但在刷新的同时会引起较明显的闪烁尤其是当画面面积较大、图像元素过多时尤为明显甚至达到无法正常工作的地步。
因此,我们需要做相应的处理。
本文介绍了采用先在内存中绘制图形,然后再把绘好的图形以位图方式从内存拷贝到窗口客户的消除刷屏闪烁的一种方法。
WM_PAINT消息和无效区·在用户移动窗口或显示窗口时,窗口中先前被隐藏的区域重新可见。
·用户改变窗口的大小。
·滚动窗口用户区。
·程序调用InvalidateRect或InvalidateRgn函数显式地发送一条WM_PAINT消息。
当上面情况之一发生时,就要求应用程序一定刷新其用户区的一部分或全部,Windows会向窗口函数发送一条WM_PAINT消息。
另外,当 Windows删除覆盖窗口部分区域的对话框或消息框时和菜单下拉出来又被释放时窗口用户区被临时覆盖,系统会试图保存显示区域,但是不一定能成功,可能向窗口函数发送一条WM_PAINT消息,要求应用程序刷新其用户区。
需要说明的是:光标或图符穿过窗口用户区时,也可能覆盖显示内容,但这种情况下,系统一定能保留并恢复被覆盖的区域,所以此时并不会发送WM_PAINT消息来要求应用程序去刷新其显示区。