您的位置:首页 > 其它

Invalidate()InvalidateRect()UpdateWindow()三者的区别

2018-02-07 08:29 417 查看
Invalidate():不立即更新。作用区域是整个窗口客户区,将客户区标记为无效,并将WM_PAINT放到消息队列中。

InvalidateRect():立即更新。作用区域是指定矩形区,绕过消息队列直接将WM_PAINT发往窗口对象,并立即执行WM_PAINT。

UpdateWindow():立即更新。作用区域是整个窗口客户区,先判断客户区是否存在无效区域,若有无效区域,则绕过消息队列直接将WM_PAINT发往窗口对象,并立即执行WM_PAINT;若没有无效区域,返回,不执行任何操作。

 

详细说明如下:

void Invalidate( BOOL bErase = TRUE );

void InvalidateRect( LPCRECT lpRect, BOOL bErase = TRUE );

void UpdateWindow( );

这是三个函数的原函数。前两个函数中有个参数bErase,表示否要在WM_PAINT消息前发送WN_ERASEBKGND。

若为TRUE,发送;从而调用WN_ERASEBKGND来擦除一次背景,也就是用背景色将所选区域覆盖一次;

若为FALSE,不发送,不进行背景的擦除,也就是不用背景色覆盖,直接在当前区域绘制。

 

关于OnEraseBkgnd():

afx_msg BOOL OnEraseBkgnd( CDC*pDC );

当CWnd对象的背景需要被擦除时(例如,当窗口大小被改变时),框架就调用这个函数。它被调用以便为绘图准备无效区域。

返回值的具体含义是:

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

FALSE表示画之前不用背景色覆盖,直接绘制。

所以为了提高效率和消除闪烁,一般取值为FALSE。

 

OnEraseBkgnd是在窗口大小发生改变等情况下发生的,它将绘制窗口背景;

OnCtlColor是当窗口的控件需要绘制时发生的,它将绘制窗口的控件。

调用时机:

OnEraseBkgnd :在窗口背景需要重绘时调用.

OnPaint : 此时OnEraseBkgnd已经调用过了,所以在此响应函数体内对背景进行的操作将覆盖OnEraseBkgnd中所做的操作.

OnCtlColor : 由于在窗口将要被(第一次)绘制时响应,子窗口可以通过发送WM_CTLCOLOR请求父窗口传来一个HBRUSH.

 

Invalidate():标记一个需要重绘的无效区域,并将一个WM_PAINT放到消息队列中,但是并不立即重绘,这是因为WM_PAINT消息的优先级很低,必须等到系统执行WM_PAINT时进行重绘。这一点类似PostMessage(WM_PAINT)。若Invalidate之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,但当函数执行完毕后,消息处理才得以进行。所以不管Invalidate放在函数哪里,都是函数最后执行的。
InvalidateRect(hWnd,&rect,TRUE);作用对象是窗口的指定区域。无论窗口客户区是否无效,都向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制。因为是绕过消息队列直接向客户区窗口发送WM_PAINT消息,所以客户区会立刻执行WM_PAINT消息来进行重绘。rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,执行顺序是WM_ERASEBKGND->WM_PAINT。
UpdateWindow()的作用对象是窗口的整个客户区。该函数也是绕过消息队列直接向客户区窗口发送WM_PAINT消息,并且只向窗体发送WM_PAINT消息。但在发送之前会调用GetUpdateRect(hWnd,NULL,TRUE)来判断看有无可绘制的客户区域,如果没有,则不发送WM_PAINT消息。只要客户区有一部分是无效的,UpdateWindow()就会导致整个客户区的重绘。注意UpdateWindow()并不会导致窗口客户区无效,若窗口客户区都是有效的,那么调用UpdateWindow()并不会引起重绘操作。
 
如果希望立即重绘客户区,可以在调用Invalidate()之后调用UpdateWindow(),这样Invalidate()就会令窗口客户区无效,并将WM_PAINT消息发往消息队列。然后UpdateWindow()的调用会导致WM_PAINT立即调用,从而重绘客户区。
即:
Invalidate(False);
UpdateWindow();
等效于
InvalidateRect(hWnd,NULL,False);
 
如果客户区的任一部分无效,则UpdateWindow()将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow()调用之后的语句。
 
UpdateData()用于控件和变量的更新。
参数为:

TRUE:控件>变量(将控件上显示的数据更新到控件内的变量中,用于输入)

FALSE:变量->控件(将控件内的变量更新到控件的输出显示上,用于输出显示)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: