窗口刷新的几个函数:Invalidate UpdateWindow RedrawWindow(转)

来源:互联网 发布:微信支付接口文档java 编辑:程序博客网 时间:2024/05/17 07:34
http://blog.163.com/danshiming@126/blog/static/109412748201012621425989/一:什么时候才会发生重绘窗口的消息? 当需要更新或重新绘制窗口的外观时,应用程序就会发送WM_PAINT消息。对窗口进行重新绘制。二:Invalidate() -- RedrawWindow() -- UpdateWindow()三个函数有什么异同? Invalidate()是强制系统进行重画,但是不一定就马上进行重画。因为Invalidate()只是通知系统,此时的窗口已经变为无效。强制系统调用WM_PAINT,而这个消息只是Post就是将该消息放入消息队列。当执行到WM_PAINT消息时才会对敞口进行重绘。 UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT。 RedrawWindow()则是具有Invalidate()和UpdateWindow()的双特性。声明窗口的状态为无效,并立即更新窗口,立即调用WM_PAINT消息处理。三:刷新组合InvalidateRect(hctrl,null,true) ;UpdateWindow(hctrl);这两个函数组合起来是什么意思呢?InvalidateRect是会触发WM_PAINT事件,但是不是立即就触发,一般都会等当前操作的过程结束才触发,如果需要立即触发,那么配合UpdateWindow()使用就可以了。先执行InvalidateRect,再执行UpdateWindow(). 还有一篇文章也可以,不过好像有些问题。http://read.newbooks.com.cn/info/144737.htmlInvalidate在消息队列中加入一条WM_PAINT消息,其无效区为整个客户区。UpdateWindow直接发送一个WM_PAINT消息,其无效区范围就是消息队列中WM_PAINT消息(最多只有一条)的无效区。效果很明显,当调用Invalidate之后,屏幕不一定马上更新,因为WM_PAINT消息不一定在队列头部,而调用UpdateWindow会使WM_PAINT消息马上执行的,绕过了消息队列。如果调用Invalidate之后想马上更新屏幕,那就加上UpdateWindow()这条语句。MSDN的解释UpdateWindowThe UpdateWindow function updates the client area of the specified window by sending a WM_PAINTmessage to the window if the window's update region is not empty. The function sends a WM_PAINT message directly to the window procedure of the specified window, bypassing the application queue.If the update region is empty, no message is sent. InvalidateRectThe system sends a WM_PAINT message to a window whenever its update region is not empty and there are no other messages in the application queue for that window. 翻译成中文大概的解释如下: UpdateWindow:如果有无效区,则马上sending a WM_PAINT message到窗口处理过程,不进消息队列进行排队等待,立即刷新窗口,否则,什么都不做。 InvalidateRect:设置无效区,如果为NULL参数,则设置整个窗口为无效区。当应用程序的那个窗口的消息队列为空时,则sending a WM_PAINT message(即使更新区域为空).在sending a WM_PAINT message的所有InvalidateRect的更新区域会累加。 1:设置无效区 InvalidateRect 2:立即刷新 UpdateWindow();如果不调用 InvalidateRect就调用 UpdateWindow,那么UpdateWindow什么都不做。 (因为没有无效区)如果调用 InvalidateRect 后不调用UpdateWindow,则系统会自动在窗口消息队列为空的时候,系统自动发送一WM_PAINT消息。(有无效区也有消息WM_PAINT,但是消息在队列里,不一定能立即执行。)调用UpdateWindow()时将会发送一个WM_PAINT消息,而应用程序在接收到WM_PAINT消息后,将自动地调用Invalidate(),所以,在程序代码中,不一定要出现Invalidate()!UpdateWindow()就是立即发送WM_PAINT消息,只对声明无效的区域起作用, Invalidate()则是声明无效的方式之一。Invalidate()表示客户区域无效,在下次WM_PAINT发生时重绘。而WM_PAINT是由系统进行维护的,每当CWnd的更新区域不为空,并且在应用程序的窗口消息队列中没有其它消息时,Windows就发送一条WM_PAINT消息。 Invalidate里面有个bool型的参数,用来标识重绘的时候是否用背景色填充。是不是用SetBkcolor函数?下去继续研究。 updateWindow则是要求系统对区域进行立即重绘。 看到有人在网上提出问题,他在Invalidate后面又写了绘图的函数但是没有执行,因为invalidate执行过以后转到PAINT命令了。所以后面的都没有显示。 也终于想通我绘的图一直在闪啊闪,因为我在PAINT里面用到Invalidate()函数,所以他不停的自嵌套,倒是绘的图不停的闪。Invalidate让客户区处于可以重画的状态,而UpdateWindow开始重画,但是它先判断客户区是否为空,不空UpdateWindow不执行,为空才执行重画。Invalidat最后也是调用InvalidatRect,在windows API里只有InvalidatRect的 ===================补充========1=================================================CWnd::RedrawWindowBOOL RedrawWindow( LPCRECT lpRectUpdate = NULL, CRgn* prgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE );返回值:如果窗口被成功地重画,则返回非零值;否则返回0。参数:lpRectUpdate 指向一个RECT结构,其中包含了更新区域的坐标。如果prgnUpdate中包含了有效的区域句柄,则这个参数将被忽略。prgnUpdate 表示了更新区域。如果prgnUpdate和lpRectUpdate都为NULL,则整个客户区将被加入更新区域。 flags 下面的标志被用于使窗口无效:RDW_ERASE 使窗口在重画时接收到一个WM_ERASEBKGND消息。必须同时指定RDW_INVALIDATE标志;否则RDW_ERASE标志将没有效果。RDW_FRAME 使窗口非客户区中与更新区域重叠的任何部分接收到一条WM_NCPAINT消息。必须同时指定RDW_INVALIDATE标志,否则RDW_FRAME标志将没有效果。RDW_INTERNALPAINT 使一条WM_PAINT消息被传递到窗口,而不管窗口是否包含一个无效区域。RDW_INVALIDATE 使lpRectUpdate或prgnUpdate(仅有一个可能为NULL)无效。如果这个两个参数都为NULL,则整个窗口都无效。下面的标志被用于使窗口有效:RDW_NOERASE 禁止任何未处理的WM_ERASEBKGND消息。RDW_NOFRAME 禁止任何未处理的WM_NCPAINT消息。这个标志必须与RDW_VALIDATE一起使用,通常也与RDW_NOCHILDREN一起使用。这个选项必须小心使用,因为它可能会使窗口的某些部分不能正确地画出。RDW_NOINTERNALPAINT 禁止任何未处理的内部WM_PAINT消息。这个标志不影响从无效区域产生的WM_PAINT消息。RDW_VALIDATE 使lpRectUpdate或prgnUpdate(仅有一个可能为NULL)有效。如果这个两个参数都为NULL,则整个窗口都有效。这个标志不影响内部WM_PAINT消息。下面的标志控制着何时产生重画动作。除非指定了这些位,否则RedrawWindow函数不会执行绘图动作。RDW_ERASENOW 如果有必要,则在函数返回前使涉及的窗口(如RDW_ALLCHILDREN和RDW_NOCHILDREN标志所指定的)接收到WM_NCPAINT和WM_ERASEBKGND消息。WM_PAINT消息将被延缓。RDW_UPDATENOW 如果有必要,则在函数返回前使涉及的窗口(如RDW_ALLCHILDREN和RDW_NOCHILDREN标志所指定的)接收到WM_NCPAINT,WM_ERASEBKGND和WM_PAINT消息。在缺省情况下,RedrawWindow函数影响的窗口依赖于指定的窗口是否具有WS_CLIPCHILDREN风格。WS_CLIPCHILDREN窗口的子窗口不会被影响。但是,那些不具有WS_CLIPCHILDREN风格的窗口将被递归地有效或无效,直到遇见具有WS_CLIPCHILDREN风格的窗口。下面的标志控制着RedrawWindow函数将影响哪些窗口:RDW_ALLCHILDREN 在重画操作中包含子窗口,如果有的话。RDW_NOCHILDREN 在重画操作中不包括子窗口,如果有的化。说明:这个函数更新给定窗口的客户区中指定的矩形或区域。当RedrawWindow成员函数被用于使捉摸窗口的部分无效的时候,该窗口不接收 ============================补充========2==============================================CWnd::InvalidateRectvoid InvalidateRect( LPCRECT lpRect, BOOL bErase = TRUE );参数:lpRect 指向一个CRect对象或RECT结构,其中包含了要被加入更新区域的矩形(客户区坐标)。如果lpRect为NULL,则整个客户区都被加入更新区域。bErase 指定更新区域内的背景是否要被擦除。 说明:这个函数将给定的客户区矩形加入CWnd更新区域,使该区域无效。无效的矩形与更新区域内的其它区域一起被标记为在发送下一条WM_PAINT消息时需要重画。无效的区域在更新区域内累积,直到发生下一次WM_PAINT调用,这个区域被处理为止,或者直到这个区域被ValidateRect或ValidateRgn成员函数标为有效为止。bErase参数指定了在处理更新区域的时候是否要擦除更新区域内的背景。如果bErase为TRUE,则当调用BeginPaint函数的时候,将擦除背景。如果bErase为FALSE,则背景保持不变。如果对于更新区域的任何部分bErase为TRUE,则整个区域的背景都会被擦除,而不仅是给定的部分。当CWnd的更新区域不为空,并且应用程序的窗口消息队列中没有其它消息时,Windows就发送一条WM_PAINT消息。 ===========================补充======3================================================ CWnd::UpdateWindowvoid UpdateWindow( );说明:如果更新区域不为空,则发送一条WM_PAINT消息以更新客户区域。UpdateWindow成员函数直接发送一条WM_PAINT消息,越过应用程序队列。如果更新区域为空,则WM_PAINT不会被发送。
0 0