emWIN里面的无效重绘和windows很类似。

WM_InvalidateArea()和WM_InvalidateRect()只重绘指定的区域,其他区域不会重绘,这样避免了闪烁,重绘发生在下次WM_PAINT消息中。
WM_InvalidateWindow()重绘整个窗口,可以看到明显的闪烁。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

InvalidateRect函数中的参数TRUE表示系统会在你画之前用背景色将所选区域覆盖一次,默认背景色为白色,可以通过设置BRUSH来改变背景色。

Invalidate()之后:
...OnPaint()->OnPrepareDC()->OnDraw()
所以只是刷新在OnPaint()和OnDraw()函数中的绘图语句。其它地方没有影响。

Invalidate标记一个需要重绘的无效区域,并不意味着调用该函数后就立刻进行重绘。类似于PostMessage(WM_PAINT),需要处理到WM_PAINT消息时才真正重绘。因为您Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。

Invalidate只是放一个WM_PAINT消息在队列里,不做别的,所以只有当当前函数返回后,进入消息循环,取出WM_PAINT,才执行PAINT,所以不管Invalidate放哪里,都是最后的。

InvalidateRect(hWnd,&rect,TRUE);

向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,
rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。
UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT

如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。(windows程序设计第5版 P98)

UpdateData()顺便说下,这个函数不是刷新界面用的。
UpdateData();参数为FALSE时,将界面上控件绑定的变量的数据导到控件内,参数为TRUE时,导入方向则相反

附:Invalidate 与WM_PAINT之间的关系

系统会在多个不同的时机发送WM_PAINT消息:当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时,等等,这些动作都是由系统管理的,应用只是被动地接收该消息,在消息处理函数中进行绘制操作;大多数的时候应用也需要能够主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,这一般是通过InvalidateRect和 InvalidateRgn函数来完成的。InvalidateRect和InvalidateRgn把指定的区域加到窗口的Update Region中,当应用的消息队列没有其他消息时,如果窗口的Update Region不为空时,系统就会自动产生WM_PAINT消息。

系统为什么不在调用Invalidate时发送WM_PAINT消息呢?又为什么非要等应用消息队列为空时才发送WM_PAINT消息呢?这是因为系统把在窗口中的绘制操作当作一种低优先级的操作,于是尽可能地推后做,这样有利于提高绘制的效率:在两个WM_PAINT消息之间多个Invalidate调用使之失效的区域就会被累加起来,然后在一个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是否为空等

csdn:我调试程序单步执行,在OnPaint()进入处设置了断点,在程序首次进入OnPaint()前,有几处Invalidate()调用,我发现Invalidate()执行后就继续执行下面的语句了,并没有进入OnPaint(),为什么呀? 还有就是OnPaint()的首次执行是由什么引发的?
OnPaint()消息的优先级比较低啊

要想立即执行OnPaint(),可以调用API函数UpdateWindow(hwnd);//hwnd为窗口句柄.

1.是进入消息循环,它从消息队列中提取各个窗口的消息,然后分派到各个窗口的窗口过程 
2.一个窗口的多个WM_PAINT,在一次消息循环中统一处理,就是说只调用一次OnPaint. 
3.立即刷新可以调用UpdateWindow,WM_PAINT也会在调用该函数后从消息队列中除去.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Invalidate与UpdateWindow

Invalidate()函数

Msdn:

Invalidates the entire client area of CWnd. The client area is marked for painting when the nextWM_PAINTmessage occurs. The region can also be validated before aWM_PAINT message occurs by theValidateRect orValidateRgn member function. (使客户区域无效。)

UpdateWindow( )函数

Msdn:

Updates the client area by sending a WM_PAINT message if the update region is not empty. TheUpdateWindow member function sends aWM_PAINT message directly, bypassing the application queue. If the update region is empty,WM_PAINT is not sent.(如果更新区域不为空,则通过发送WM_PAINT消息来更新客户区。UpdateWindow函数直接发送WM_PAINT消息,不经过应用程序的消息队列。如果更新区域为空,则不发送WM_PAINT消息)

从msdn的解释可以看出,Invalidate只是标志无效区域,而不是立即更新客户区域,若要想立即更新,则要在Invalidate后执行UpdateWindow语句,该函数通过发送WM_PAINT消息可以立即更新客户区域(更新区域不为空的情况下)。

而通过在debug下跟踪TRACE语句输出也验证了上面的观点,若只调用Invalidate函数,则必须在程序的所有语句执行完毕后OnPaint函数才会响应。相反,若在执行Invalidate函数后立即执行UpdateWindow函数,则程序会在执行UpdateWindow函数后立即发送WM_PAINT消息,OnPaint函数去响应,之后再去执行UpdateWindow后面的语句。

下面这两段代码非常有意思,它们是按钮的响应函数:

  1. void CASSSDlg::OnBnClickedButton1()
  2. {
  3. Invalidate(true); //使窗口的客户区无效
  4. //UpdateWindow();
  5. CString sTemp;
  6. sTemp="能看见我么?";
  7. CClientDC dc(this);
  8. dc.TextOutW(0,0,sTemp);
  9. }
  1. //第二段:
  2. void CASSSDlg::OnBnClickedButton1()
  3. {
  4. Invalidate(true);   //使窗口的客户区无效
  5. UpdateWindow(); //发送WM_PAINT消息,立即更新窗口
  6. CString sTemp;
  7. sTemp="能看见我么?";
  8. CClientDC dc(this);
  9. dc.TextOutW(0,0,sTemp);
  10. }

这两段代码的执行效果就在于第二段代码的客户区输出了sTemp语句,而第一段代码却没有输出。原因就在于第一段代码没有立即刷新客户区,而是等到所有语句结束之后才发送WM_PAINT消息,也就是它在TextOut之后才刷新的,TextOut输出的文字给刷掉了。其实不光是TextOut,画出的图也会被刷掉。

当然了,如果第一段代码的Invalidate函数参数为false,则在客户区也能看见TextOutW的输出,这个原因虽然它也是等到所有语句结束之后才发送WM_PAINT消息,但由于Invalidate函数的参数若为false,则不擦除背景(TextOut的输出做为背景被保留下来了),若为true,则用默认画刷擦除背景,即TextOut输出的文字给背景刷掉了。

原文:http://blog.csdn.net/liuy_yy/article/details/7190331

InvalidateRect只是增加重绘区域,在下次WM_PAINT的时候才生效的更多相关文章

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

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

  2. MFC中 Invalidate() , InvalidateRect() , UpdateWindow(), Redrawwindow() 区别

    1. void Invalidate( BOOL bErase = TRUE ); 该函数的作用是使整个窗口客户区无效.窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口 ...

  3. MFC窗口重绘

    Invalidate()与 UpdateAllViews()有什么分别 Invalidate()是让程序重画窗口. UpdateAllViews()是在DOC/VIEW结构中, 当一个视图的数据改变后 ...

  4. InvalidateRect()与Invalidate()的用法(转)

    BOOL InvalidateRect(   HWND hWnd,           // 窗口句柄   CONST RECT* lpRect,   // 矩形区域   BOOL bErase    ...

  5. 窗口绘制有关的消息整理 WM_PAINT, WM_NCPAINT, WM_ERASEBKGND

    WM_PAINTWM_PAINT是Windows窗口系统中一条重要的消息,应用程序通过处理该消息实现在窗口上的绘制工作. WM_NCPAINT当窗口客户区以外的部分(如窗口标题栏.菜单栏等)需要需要重 ...

  6. Invalidate()函数

    Invalidate( ) :使整个窗口客户区无效, 并进行更新显示的函数 介绍 void Invalidate( BOOL bErase = TRUE ); 参数: bErase 决定了是否要在WM ...

  7. (十一)WebGIS中要素(Feature)的设计

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 在GIS中元素一般分为点元素,线元素,面元素以及symbol ...

  8. 《深入浅出MFC》下载

    百度云及其他网盘下载地址:点我 编辑推荐 <深入浅出MFC>内含光盘一片,书中所有原始码与可执行文件尽在其中. 作者简介 侯俊杰,先生不知何许人也,闲静少言,不慕荣利.好读书,求甚解:每有 ...

  9. MFC重绘函数:InvalidateRect(), Invalidate()和UpdateWindow()

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

随机推荐

  1. UIPickerView 创建中国地区显示 省份 市

    第一步初始化 UIPickerView *pickerview; //城市滚动表 NSDictionary *dict; //用于存储省份-城市的数据 NSArray *provinceArray; ...

  2. spring security:ajax请求的session超时处理

    当前端在用ajax请求时,如果没有设置session超时时间并且做跳转到登录界面的处理,那么只是靠后台是很难完成超时的一系列动作的:但是如果后台 没有封装一个ajax请求公共类,那么在ajax请求上下 ...

  3. kubernetes port nodePort targetPort 理解

    port The port that the service is exposed on the service's cluster ip (virsual ip). Port is the serv ...

  4. 【Python之路】第六篇--Python基础之模块

    模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...

  5. 为OLED屏增加GUI支持

    为OLED屏增加GUI支持1:OLED驱动 为OLED屏增加GUI支持2:2D图形库 为OLED屏增加GUI支持3:字库 为OLED屏增加GUI支持4:文本框控件 为OLED屏增加GUI支持5:图片控 ...

  6. 如何设置linux的文件和目录的权限

    1 字符表示法 1)chmod [-R] 权限(mode)file   注:[-R]会将目录下所有权限都设置成指定的 who operator permission u(owner) +增加权限 r( ...

  7. 线段树解决leetcode307. Range Sum Query - Mutable

    在下面的图中,求[0,0]和[1,1]区间元素和, 对于[0,0] start =0 ,end = 0, 查到root = 4 [0-1]的节点,mid = 0, 此时mid > end-1,表 ...

  8. Counting Stars

    Counting Stars 题目链接:http://acm.xidian.edu.cn/problem.php?id=1177 离线+一维树状数组 一眼扫过去:平面区间求和,1e6的数据范围,这要h ...

  9. jquery.validationEngine

    引入库文件 <!DOCTYPE html> <head> <!--jQuery--> <script type="text/javascript&q ...

  10. html中的a标签的target属性的四个值的区别?

    target属性规定了在何处打开超链接的文档. 如果在一个 <a> 标签内包含一个 target 属性,浏览器将会载入和显示用这个标签的 href 属性命名的.名称与这个目标吻合的框架或者 ...