1. 重绘消息

当需要更新或者重绘窗口时,一般系统会发出两个消息WM_PAINT(通知客户区有变化)和WM_NCPAINT(通知非客户区有变化)

  • WM_NCPAINT系统会自己搞定
  • WM_PAINT消息对应的函数是OnPaint(),它是系统默认的接受WM_PAINT消息的函数,但我们一般在程序中做重绘时都在OnDraw函数中进行的,因为在ONPAIN函数中调用了ONDRAW函数。
    ///CView默认的标准的重画函数
    void CView::OnPaint()
    {
       CPaintDC dc(this);
        OnPreparDC(&dc);
        OnDraw(&dc); //调用了OnDraw
    }
2. 重绘函数
  • InvalidateRect(&Rect)和Invalidate()两个函数形式和功能差不多,但Invalidate是使得整个窗口无效,形成无效矩形,而InvalidateRect(&Rect)是使得指定的区域无效。
  • Invalidate()申明无效,等待WM_PAINT消息以便重绘,队列中无其他消息时系统会自动发送。void Invalidate( BOOL bErase = TRUE ); 该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
  • UpdateWindow()会立即发送WM_PAINT,不过在它发送前,先调用GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制区域,如果没有则不发送消息RedrawWindow()RedrawWindow()则是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。
3. 系统消息机制
 
      系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做。不过这样也有利于提高绘制的效率:两个WM_PAINT消息之间通过InvalidateRect和InvaliateRgn使之失效的区域就会被累加起来,然后在一个WM_PAINT消息中一次得到 更新,不仅能避免多次重复地更新同一区域,也优化了应用的更新操作。像这种通过InvalidateRect和InvalidateRgn来使窗口区域无效,依赖于系统。在合适的时机发送WM_PAINT消息的机 制实际上是一种异步工作方式,也就是说,在无效化窗口区域和发送WM_PAINT消息之间是有延迟的;有时候这种延迟并不是我们希望的,这时我们当然可以在无效化窗口区域后利用SendMessage 发送一条WM_PAINT消息来强制立即重画,但不如使用Windows GDI为我们提供的更方便和强大的函数:UpdateWindow和RedrawWindow。UpdateWindow会检查窗口的Update Region,当其不为空时才发送WM_PAINT消息;RedrawWindow则给我们更多的控制:是否重画非客户区和背景,是否总是发送WM_PAINT消息而不管Update Region是否为空等。
     
 BeginPaint和WM_PAINT消息紧密相关。试一试在WM_PAINT处理函数中不写BeginPaint会怎样?程序会像进入了一个死循环一样达到惊人的CPU占用率,你会发现程序总在处理一个接 一个的WM_PAINT消息。这是因为在通常情况下,当应用收到WM_PAINT消息时,窗口的Update Region都是非空的(如果为空就不需要发送WM_PAINT消息了),BeginPaint的一个作用就是把该Update Region置为空,这样如果不调用BeginPaint,窗口的Update Region就一直不为空,如前所述,系统就会一直发送WM_PAINT消息。
      BeginPaint和WM_ERASEBKGND消息也有关系。当窗口的Update Region被标志为需要擦除背景时,BeginPaint会发送WM_ERASEBKGND消息来重画背景,同时在其返回信息里有一个标志表明窗口背景是否被重画过。当我们用InvalidateRect和InvalidateRgn来把指定区域加到Update Region中时,可以设置该区域是否需要被擦除背景,这样下一个BeginPaint就知道是否需要发送WM_ERASEBKGND消息了。
 
注:BeginPaint只能在WM_PAINT处理函数中使用。
 
 

MFC重绘函数:InvalidateRect(), Invalidate()和UpdateWindow()的更多相关文章

  1. 【转】VC的MFC中重绘函数的使用总结(整理)

    原文网址:http://www.cnblogs.com/x8023z/archive/2008/12/09/mfc33.html 在刷新窗口时经常要调用重绘函数MFC提供了三个函数用于窗口重绘Inva ...

  2. VC++中关于控件重绘函数/消息 OnPaint,OnDraw,OnDrawItem,DrawItem的区别

    而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息. OnDraw()是CVIEW的成员函数,并且没有响应消息的功能.这就是为什么你用VC成的程序代码时,在视图类只有OnDraw ...

  3. MFC重绘原理的关键理解

    // ====================Windows重绘消息与函数========================== 得到桌面窗口的句柄,然后再绘图HWND GetDesktopWindow ...

  4. Android视图重绘,使用invalidate还是requestLayout

    概述 在我们在进行自定义View的相关开发中,当我们更改了当前View的状态,比如大小,位置等,我们需要重新刷新整个界面,保证显示最新的状态.在Android中,让当前的视图重绘有两种方式,inval ...

  5. InvalidateRect,invalidate,updatewindow(转)

    InvalidateRect(HWND) 使窗口无效 产生消息WM_PAINT; ValidateRect(HWND)使窗口有效 清除消息队列中的WM_PAINT消息 在编程的时候经常把UpdateD ...

  6. 【MFC】MFC中窗口重绘

    MFC中窗口重绘 摘自:http://blog.csdn.net/shuilan0066/article/details/5859057 在刷新窗口时经常要调用重绘函数 MFC提供了三个函数用于窗口重 ...

  7. MFC 刷新函数:Invaldate,UpdateWindow,InvaldateRect

    在窗口刷新和绘制的过程中,常常需要用到窗口刷新函数.一般用于窗口图形刷新的函数有:UpdateWindows().Invaldate().InvaldateRect(). 先说UpdateWindow ...

  8. Android学习Scroller(五)——具体解释Scroller调用过程以及View的重绘

    PS: 该篇博客已经deprecated,不再维护.详情请參见  站在源代码的肩膀上全解Scroller工作机制  http://blog.csdn.net/lfdfhl/article/detail ...

  9. TGraphicControl(自绘就2步,直接自绘自己,不需要调用VCL框架提供的函数重绘所有子控件,也不需要自己来提供PaintWindow函数让管理框架来调用)与TControl关键属性方法速记(Repaint要求父控件执行详细代码来重绘自己,还是直接要求Invalidate无效后Update刷新父控件,就看透明不透明这个属性,因为计算显示的区域有所不同)

    TGraphicControl = class(TControl) private FCanvas: TCanvas; procedure WMPaint(var Message: TWMPaint) ...

随机推荐

  1. 自己做的萌萌哒的js宠物挂件~

    OwO萌物v1.1 类似wp伪春菜,但纯js不用后端,且可定制程度非常高~,3个人格示例,需要的童鞋自提 仙六 - 越祈 作者:正逍遥0716 2016/5/15 CLANNAD - 藤林杏 作者:正 ...

  2. SQL Server中的20个系统变量

    1.@@CONNECTIONS返回自上次启动 Microsoft SQL Server以来连接或试图连接的次数.示例:下面的示例显示了到当前日期和时间为止试图登录的次数.SELECT GETDATE( ...

  3. linux下vi命令笔记

    vim 编辑器 全屏编辑器 模式化编辑器 vi:Visual Interfacevim:VI iMproved vi增强版vi模式:    编辑模式(命令模式)(默认处于编辑模式)        Ct ...

  4. 第五篇:python高级之面向对象高级

    python高级之面向对象高级   python高级之面向对象高级 本节内容 成员修饰符 特殊成员 类与对象 异常处理 反射/自省 单例模式 1.成员修饰符 python的类中只有私有成员和公有成员两 ...

  5. VBA开发中的前绑定与后绑定

    凡是能用createobject创建的对象,都可以在引用相对应的运行库(library)文件之后在对象浏览器中得到它的方法.属性.枚举和事件列表,比如Shell.Application对象在Shell ...

  6. 屏蔽Codeforces做题时的Problem tags提示

    当在Codeforces上做题的时,有时会无意撇到右侧的Problem tags边栏,但是原本并不希望能够看到它. 能否把它屏蔽了呢?答案是显然的,我们只需要加一段很短的CSS即可. span.tag ...

  7. jquery选择器取值和url正则匹配

    用到的简单jquery知识,简单总结一下,一是能加深自己的记忆,二是方便自己以后查看.常言道"好记性不如烂笔头",要养成常总结.常记录的好习惯.慢慢的发现jquery很有意思,很强 ...

  8. C# - Sql数据类型的对应关系

    <Language From="SQL" To="C#"> <Type From="bigint" To="lo ...

  9. Oracle 10G强大的SQL优化工具:SQL Tuning Advisor

    p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 0); line-height: 120%; orphans: 2; widow ...

  10. ajax 操作全局监测,用户session失效

    jQuery(function ($) { // 备份jquery的ajax方法 var _ajax = $.ajax; // 重写ajax方法,先判断登录在执行success函数 $.ajax = ...