VC++重绘消息
创建、移动窗口,改变窗口大小,这些操作会调用
严格地说,只有当收到WM_PAINT消息后窗口会重绘,而引起这个消息的事件有很多,比如:首次创建 窗口,移动或者覆盖窗口,改变窗口大小等
Invalidate()标记一个需要重绘的无效区域,如果您Invalidate()之后还有其他的语句正在执行,程序没有机会去处理WM_PAINT消息,只有当函数执行完毕后,消息处理才得以进行。
Invalidate():
该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口,那么原来被遮住的部分就是无效的,需要重绘。这时Windows会在应用程序的消息队列中放置WM_PAINT消息。MFC为窗口类提供了WM_PAINT的消息处理函数OnPaint,OnPaint负责重绘窗口。视图类有一些例外,在视图类的OnPaint函数中调用了OnDraw函数,实际的重绘工作由OnDraw来完成。参数bErase为TRUE时,重绘区域内的背景将被擦除,否则,背景将保持不变。
- 当第一次创建一个窗口时,
- 当改变窗口的大小时,
- 当把窗口从另一个窗口背后移出时,
- 当最大化或最小化窗口时,等等
当需要主动引发窗口中的绘制操作,比如当窗口显示的数据改变的时候,一般可通过下面方式实现:
- void Invalidate( BOOL bErase = TRUE ); //使整个客户区窗口无效
- void InvalidateRect( LPCRECT lpRect, BOOL bErase = TRUE ); //使指定矩形区域窗口无效
Invalidat最后也是调用InvalidatRect,在windows API里只有InvalidatRect的
UpdateWindow():
UpdateWindow( )的作用是使窗口立即重绘。调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理。调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。
当第一次创建一个窗口时,当改变窗口的大小时,当把窗口从另一个窗口背后移出时,当最大化或最小化窗口时等等,操作系统会发送WM_PAINT消息。
当需要主动引发窗口中的绘制操作,可通过下面方法实现:
调用Invalidate使整个客户区窗口无效、调用InvalidatRect使指定矩形区域窗口无效从而产生WM_PAINT消息,但Invalidate最后也是调用InvalidatRect,因为在windows API里只有InvalidatRect;
调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理,这时可调用UpdateWindow,
UpdateWindow判断是否有无效区,有则马上sending a WM_PAINT message到窗口过程,此时的WM_PAINT消息不用进入消息队列排队。
RedrawWindow具有Invalidate和UpdateWindow的双特性:声明窗口的状态为无效,立即发送WM_PAINT到窗口过程并立即更新窗口。
窗体在刷新重绘时,总是先用背景色将显示区清除,然后调用OnPaint,而背景色往往与绘图内容反差很大,这样一擦一写会造成图象颜色的反差。当WM_PAINT的响应很频繁的时候,这种反差也越发明显,也就会出现闪烁现象(如果将背景刷设置成NULL,虽然重绘图形不会闪,但窗口显示会一团糟,解决:
- 用InvalidateRect函数只重绘部分区域,而且不重绘背景(最后一个参数设为FALSE)就可以解决大部分的屏闪问题。
- 使用BitBlt函数。先在内存中作图,然后用此函数将做好的图复制到前台,同时禁止背景刷新,这样就消除了闪烁(双缓冲绘图:在内存中创建与画布一致的缓冲区->在缓冲区画图->将缓冲区位图拷贝到当前画布上->释放内存缓冲区。