WM_Paint 消息詳解

轉自:http://blog.csdn.net/sdn_009/article/details/3292133


WM_PAINT 是 Windows 窗口系統中一條重要的消息,

應用程序通過處理該消息實現在窗口上的繪製工作。




1. 系統何時發送WM_PAINT消息?

   系統會在多個不同的時機發送 WM_PAINT 消息:當第一次創建一個窗口時,當改變窗口的大小時,當把窗口從另一個

窗口背後移出時,當最大化或最小化窗口時,等等,這些動作都是由 系統管理的,應用只是被動地接收該消息,在消息處理函數中進行繪製操作;大多數的時候應用也需要能夠主動引發窗口中的繪製操作,比如當窗口顯示的數據改變 的時候,這一般是通過 InvalidateRect 和 InvalidateRgn 函數來完成的。


    InvalidateRect 和 InvalidateRgn把指定的區域加到窗口的 Update Region 中,當應用的消息隊列沒有其他

消息時,如果窗口的 Update Region 不爲空時,系統就會自動產生 WM_PAINT 消息。


    系統爲什麼不在調用 Invalidate 時發送 WM_PAINT 消息呢?又爲什麼非要等應用消息隊列爲空時才發送WM_PAINT 消息呢?這是因爲系統把在窗口中的繪製操作當作一種低優先級的操作,於是儘可能地推後做。


    不過這樣也有利於提高繪製的效率:兩個 WM_PAINT 消息之間通過 InvalidateRect 和InvaliateRgn 使之失效

的區域就會被累加起來,然後在一個 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 是否爲空等。




2. BeginPaint

   BeginPaint 和 WM_PAINT 消息緊密相關。試一試在 WM_PAINT 處理函數中不寫 BeginPaint 會怎樣?程序會像

進入了一個死循環一樣達到驚人的CPU佔用率,你會發現程序總在處理一個接 一個的 WM_PAINT 消息。這是因爲在通常情

況下,當應用收到 WM_PAINT 消息時,窗口的 Update Region 都是非空的(如果爲空就不需要發送WM_PAINT 消息了), BeginPaint 的一個作用就是把該 Update Region 置爲空,這樣如果不調用 BeginPaint,窗口的Update Region 就一直不爲空,如前所述,系統就會一直髮送 WM_PAINT 消息。


    BeginPaint 和 WM_ERASEBKGND 消息也有關係。當窗口的 Update Region 被標誌爲需要擦除背景時,

BeginPaint 會發送 WM_ERASEBKGND 消息來重畫背景,同時在其返回信息裏有一個標誌表明窗口背景是否被重畫過。


    當我們用 InvalidateRect 和 InvalidateRgn 來把指定區域加到 Update Region 中時,可以設置該區域是否

需要被擦除背景,這樣下一個 BeginPaint 就知道是否需要發送 WM_ERASEBKGND 消息了。


    另外要注意的一點是,BeginPaint 只能在 WM_PAINT 處理函數中使用。


 


補充幾點:

1.WM_Paint 是一個被動消息,不能通過普通的方法簡單的 sendmessage WM_paint 了事
這是不行的;但通過消息由程序員引發不是不可能;通過幾個特殊的常數可以做到,不過要到delphi下找

2.sendmessage 可以將消息發送到消息隊列;但windows會自動判斷是否存在無效的畫圖區域;
如果存在無效的畫圖區域,則可能會重畫,反之則棄用該消息.

3.可以使用 InvalidateRect 等幾個APi將屏幕上任意一個個矩形區域設置爲無效區域,在UpdateWindow後調用後,windows會自動查找是否存在無效,並重畫,該矩形區域;

發佈了1 篇原創文章 · 獲贊 13 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章