WM_Paint 消息疑问解析
1. 系統(tǒng)何時發(fā)送WM_PAINT消息?
?? 系統(tǒng)會在多個不同的時機發(fā)送 WM_PAINT 消息:當(dāng)?shù)谝淮蝿?chuàng)建一個窗口時,當(dāng)改變窗口的大小時,當(dāng)把窗口從另一個
窗口背后移出時,當(dāng)最大化或最小化窗口時,等等,這些動作都是由 系統(tǒng)管理的,應(yīng)用只是被動地接收該消息,在消息處理函數(shù)中進行繪制操作;大多數(shù)的時候應(yīng)用也需要能夠主動引發(fā)窗口中的繪制操作,比如當(dāng)窗口顯示的數(shù)據(jù)改變 的時候,這一般是通過 InvalidateRect 和 InvalidateRgn 函數(shù)來完成的。
?
??? InvalidateRect 和 InvalidateRgn把指定的區(qū)域加到窗口的 Update Region 中,當(dāng)應(yīng)用的消息隊列沒有其他
消息時,如果窗口的 Update Region 不為空時,系統(tǒng)就會自動產(chǎn)生 WM_PAINT 消息。
?
??? 系統(tǒng)為什么不在調(diào)用 Invalidate 時發(fā)送 WM_PAINT 消息呢?又為什么非要等應(yīng)用消息隊列為空時才發(fā)送WM_PAINT 消息呢?這是因為系統(tǒng)把在窗口中的繪制操作當(dāng)作一種低優(yōu)先級的操作,于是盡可能地推后做。
?
??? 不過這樣也有利于提高繪制的效率:兩個 WM_PAINT 消息之間通過 InvalidateRect 和InvaliateRgn 使之失效
的區(qū)域就會被累加起來,然后在一個 WM_PAINT 消息中一次得到 更新,不僅能避免多次重復(fù)地更新同一區(qū)域,也優(yōu)化了
應(yīng)用的更新操作。
??? 這種通過 InvalidateRect 和 InvalidateRgn 來使窗口區(qū)域無效,依賴于系統(tǒng)在合適的時機發(fā)送 WM_PAINT
消息的機 制實際上是一種異步工作方式,也就是說,在無效化窗口區(qū)域和發(fā)送 WM_PAINT 消息之間是有延遲的;有時候
這種延遲并不是我們希望的,這時我們當(dāng)然可以在無效化窗口區(qū)域后利用 SendMessage? 發(fā)送一條 WM_PAINT消息來強
制立即重畫,但不如使用 Windows GDI 為我們提供的更方便和強大的函數(shù): UpdateWindow 和 RedrawWindow。
?
?? UpdateWindow 會檢查窗口的 Update Region,當(dāng)其不為空時才發(fā)送 WM_PAINT 消息; RedrawWindow 則給我
們更多的控制:是否重畫非客戶區(qū)和背景,是否總是發(fā)送 WM_PAINT 消息而不管 Update Region 是否為空等。
?
--------------------------------------------------------------------------------
2. BeginPaint
?? BeginPaint 和 WM_PAINT 消息緊密相關(guān)。試一試在 WM_PAINT 處理函數(shù)中不寫 BeginPaint 會怎樣?程序會像
進入了一個死循環(huán)一樣達到驚人的CPU占用率,你會發(fā)現(xiàn)程序總在處理一個接 一個的 WM_PAINT 消息。這是因為在通常情
況下,當(dāng)應(yīng)用收到 WM_PAINT 消息時,窗口的 Update Region 都是非空的(如果為空就不需要發(fā)送WM_PAINT 消息了), BeginPaint 的一個作用就是把該 Update Region 置為空,這樣如果不調(diào)用 BeginPaint,窗口的Update Region 就一直不為空,如前所述,系統(tǒng)就會一直發(fā)送 WM_PAINT 消息。
?
??? BeginPaint 和 WM_ERASEBKGND 消息也有關(guān)系。當(dāng)窗口的 Update Region 被標(biāo)志為需要擦除背景時,
BeginPaint 會發(fā)送 WM_ERASEBKGND 消息來重畫背景,同時在其返回信息里有一個標(biāo)志表明窗口背景是否被重畫過。
?
??? 當(dāng)我們用 InvalidateRect 和 InvalidateRgn 來把指定區(qū)域加到 Update Region 中時,可以設(shè)置該區(qū)域是否
需要被擦除背景,這樣下一個 BeginPaint 就知道是否需要發(fā)送 WM_ERASEBKGND 消息了。
?
??? 另外要注意的一點是,BeginPaint 只能在 WM_PAINT 處理函數(shù)中使用。
總結(jié)
以上是生活随笔為你收集整理的WM_Paint 消息疑问解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决:Error response fr
- 下一篇: AI:初学者如何从零学习人工智能?看完你