1. 程式人生 > >MFC 視窗重繪

MFC 視窗重繪

      系統為什麼不在呼叫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是否為空等。
BeginPaint和WM_PAINT訊息緊密相關。試一試在WM_PAINT處理函式中不寫BeginPaint會怎樣?程式會像進入了一個死迴圈一樣達到
驚人的CPU佔用率,你會發現程式總在處理一個接 一個的WM_PAINT訊息。這是因為在通常情況下,當應用收到WM_PAINT訊息時,窗口的Update Region都是非空的(如果為空就不需要傳送WM_PAINT訊息了),BeginPaint的一個作用就是把該Update Region置為空,這樣如果不呼叫BeginPaint,視窗的Update Region就一直不為空,如前所述,系統就會一直髮送WM_PAINT訊息。