Invalidate

Invalidate( ) :使整個視窗客戶區無效, 並進行更新顯示的函式

介紹

void Invalidate( BOOL bErase = TRUE );

參數: bErase 決定了是否要在WM_PAINT訊息前傳送WM_ERASEBKGND

視窗的客戶區無效意味著需要重繪,例如,如果一個被其它視窗遮住的視窗變成了前台視窗,那么原來被遮住的部分就是無效的,需要重繪。這時Windows會在應用程式的訊息佇列中放置WM_PAINT訊息。MFC為視窗類提供了WM_PAINT的訊息處理函式OnPaint,OnPaint負責重繪視窗。視圖類有一些例外,在視圖類的OnPaint函式中調用了OnDraw函式,實際的重繪工作由OnDraw來完成。參數bErase為TRUE時,重繪區域內的背景將被擦除,否則,背景將保持不變。

區別

UpdateWindow( )的作用是使視窗立即重繪。調用Invalidate等函式後視窗不會立即重繪,這是由於WM_PAINT訊息的優先權很低,它需要等訊息佇列中的其它訊息傳送完後才能被處理。調用UpdateWindow函式可使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是否為空等。

相關詞條

相關搜尋

熱門詞條

聯絡我們