InvalidateRect(HWND) 使視窗無效 產生訊息WM_PAINT;
InvalidateRect(HWND)使視窗有效 清除訊息佇列中的WM_PAINT訊息
在編程的時候經常把UpdateData、Invalidate、InvalidateRect和UpdateWindow四個函數混淆,在這裡將簡單介紹它們的區別。
UpdateData():
當你使用了ClassWizard建立了控制項和變數之間的聯絡後:當你修改了變數的值,而希望對話方塊控制項更新顯示,就應該在修改變數後調用UpdateData(FALSE);如果你希望知道使用者在對話方塊中到底輸入了什麼,就應該在訪問變數前調用UpdateData(TRUE),將控制項的輸入映射到變數中。
Invalidate():
該函數的作用是使整個視窗客戶區無效。視窗的客戶區無效意味著需要重繪,例如,如果一個被其它視窗遮住的視窗變成了前台視窗,那麼原來被遮住的部分就是無效的,需要重繪。這時Windows會在應用程式的訊息佇列中放置WM_PAINT訊息。MFC為視窗類別提供了WM_PAINT的訊息處理函數OnPaint,OnPaint負責重繪視窗。視圖類有一些例外,在視圖類的OnPaint函數中調用了OnDraw函數,實際的重繪工作由OnDraw來完成。參數bErase為TRUE時,重繪地區內的背景將被擦除,否則,背景將保持不變。
Invalidate標記一個需要重繪的無效地區,並不意味著調用該函數後就立刻進行重繪。 Invalidate只是放一個WM_PAINT訊息在隊列裡,不做別的,所以只有噹噹前函數返回後,進入訊息迴圈,取出WM_PAINT,才執行PAINT,所以不管Invalidate放函數哪個地方,(作用相當於)都是(放在)最後的(但並不是推薦你一律放在函數最後一行)。
InvalidateRect():
該函數的功能與Invalidate基本一樣,不同的是,它是使指定的某個地區無效,需要輸入一個地區。
UpdateWindow():
UpdateWindow( )的作用是使視窗立即重繪。調用Invalidate等函數後視窗不會立即重繪,這是由於WM_PAINT訊息的優先順序很低,它需要等訊息佇列中的其它訊息發送完後才能被處理。調用UpdateWindow函數可使WM_PAINT被直接發送到目標視窗,從而導致視窗立即重繪。
只將視窗顯示地區標記為無效以產生WM_PAINT訊息,對於某些應用程式來說也許不是完全令人滿意的選擇。在呼叫InvalidateRect之後,Windows將WM_PAINT訊息放入訊息佇列中,最後由視窗訊息處理常式處理它。然而,Windows將WM_PAINT訊息當成低優先順序訊息,如果系統有許多其它的動作正在發生,那麼也許會讓您等待一會兒工夫。這時,當對話方塊消失時,將會出現一些空白的「洞」,程式仍然等待更新它的視窗。
如果您希望立即更新無效地區,可以在呼叫InvalidateRect之後呼叫UpdateWindow:
UpdateWindow (hwnd) ;
如果顯示地區的任一部分無效,則UpdateWindow將導致Windows用WM_PAINT訊息呼叫視窗訊息處理常式(如果整個顯示地區有效,則不呼叫視窗訊息處理常式)。這一WM_PAINT訊息不進入訊息佇列,直接由Windows呼叫視窗訊息處理常式。視窗訊息處理常式完成更新後立即退出,Windows將控制傳回給程式中UpdateWindow呼叫之後的敘述。
您可能注意到,UpdateWindow與WinMain中用來產生第一個WM_PAINT訊息的函數相同。最初建立視窗時,整個顯示地區內容變為無效,UpdateWindow指示視窗訊息處理常式繪製顯示地區。
-----------------------------------------------------------------------
1. UpdateWindow:如果有無效區,則馬上sending a WM_PAINT message到視窗處理過程,不進訊息佇列進行排隊等待,立即重新整理視窗,否則,什麼都不做。
2. InvalidateRect:設定無效區,如果為NULL參數,則設定整個視窗為無效區。當應用程式的那個視窗的訊息佇列為空白時,則sending a WM_PAINT message(即使更新地區為空白).在sending a WM_PAINT message的所有InvalidateRect的更新地區會累加。
3. 如果不調用 InvalidateRect就調用 UpdateWindow,那麼UpdateWindow什麼都不做。 ??????
4. 如果調用 InvalidateRect 後不調用UpdateWindow,則系統會自動在視窗訊息佇列為空白的時候,系統自動發送一WM_PAINT訊息。
5. 調用UpdateWindow()時將會發送一個WM_PAINT訊息,而應用程式在接收到WM_PAINT訊息後,將自動地調用Invalidate(),所以,在程式碼中,不一定要出現Invalidate()!
6. UpdateWindow()就是立即發送WM_PAINT訊息,只對聲明無效的地區起作用。Invalidate()則是聲明無效的方式之一。
7. Invalidate()表示用戶端區域無效,在下次WM_PAINT發生時重繪。而WM_PAINT是由系統進行維護的,每當CWnd的更新地區不為空白,並且在應用程式的視窗訊息佇列中沒有其它訊息時,Windows就發送一條WM_PAINT訊息。
Invalidate裡面有個bool型的參數,用來標識重繪的時候是否用背景色填充。
8. updateWindow則是要求系統對地區進行立即重繪。
看到有人在網上提出問題,他在Invalidate後面又寫了繪圖的函數但是沒有執行,因為invalidate執行過以後轉到PAINT命令了。所以後面的都沒有顯示。
也終於想通我繪的圖一直在閃啊閃,因為我在PAINT裡面用到Invalidate()函數,所以他不停的自嵌套,倒是繪的圖不停的閃。
9. Invalidate讓客戶區處於可以重畫的狀態,而UpdateWindow開始重畫,但是它先判斷客戶區是否為空白,不空UpdateWindow不執行,為空白才執行重畫。
10.Invalidat最後也是調用InvalidatRect,在windows API裡只有InvalidatRect的