日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

【转】VC窗口刷新InvalidateRect和UpdateWindow RedrawWindow

發(fā)布時(shí)間:2025/3/12 c/c++ 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】VC窗口刷新InvalidateRect和UpdateWindow RedrawWindow 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
首先說(shuō)說(shuō)WM_PAINT 這個(gè)重要的消息:

  The WM_PAINT message is generated by the system and should not be sent by an application.The system sends this message when there are no other messages in the application's message queue

  也就是說(shuō)WM_PAINT消息是由系統(tǒng)產(chǎn)生,非要等應(yīng)用程序的消息隊(duì)列為空時(shí)才發(fā)送WM_PAINT消息,并且 該消息不應(yīng)該被程序(自己寫(xiě)代碼用SendMessage)來(lái)發(fā)送。

  當(dāng)調(diào)用UpdateWindow函數(shù),或者是Window檢測(cè)到 窗口被覆蓋的地方需要恢復(fù)的時(shí)候,比如,第一次創(chuàng)建窗口,改變了窗口的大小,最大化,最小化等等(其實(shí)這些事件發(fā)生時(shí)會(huì)調(diào)用UpdateWindow函 數(shù),由該函數(shù)發(fā)送WM_PAINT消息),它會(huì)向用戶(hù)程序發(fā)送一個(gè)WM_PAINT消息。窗口過(guò)程收到WM_PAINT消息后,并不代表整個(gè)客戶(hù)區(qū)都需要 被刷新,有可能客戶(hù)區(qū)被覆蓋的區(qū)域只有一小塊,這個(gè)區(qū)域叫做“無(wú)效區(qū)域”,程序只需要更新這個(gè)區(qū)域。與WM_TIMER消息類(lèi)似,WM_PAINT消息也 是一個(gè)低級(jí)別的消息,雖然它不會(huì)像WM_TIMER消息一樣被丟棄,但Windows總是在消息循環(huán)空的時(shí)候才把WM_PAINT放入其中。

  無(wú)效區(qū)域的坐標(biāo)并不附帶在WM_PAINT消息的參數(shù)中,在程序中有其他方法可以獲取。WM_PAINT消息只 是通知程序有個(gè)區(qū)域需要更新而已,所以Windows也不會(huì)同時(shí)將兩條WM_PAINT消息放入消息循環(huán)中。當(dāng)Windows要放入一條WM_PAINT 消息的時(shí)候,如果發(fā)現(xiàn)已經(jīng)存在一個(gè)無(wú)效區(qū)域了,那么它只需要把新舊兩個(gè)無(wú)效區(qū)域合并計(jì)算出一個(gè)無(wú)效區(qū)域就可以了,消息循環(huán)中還是只需要一條 WM_PAINT消息。

  實(shí)際上,Windows為每個(gè)窗口維護(hù)一個(gè)“繪圖信息結(jié)構(gòu)”,無(wú)效區(qū)域的坐標(biāo)就在其中,每當(dāng)消息循環(huán)空的時(shí)候, 如果Windows發(fā)現(xiàn)存在一個(gè)無(wú)效區(qū)域,就會(huì)放入一個(gè)WM_PAINT消息。那么“繪圖信息結(jié)構(gòu)”怎么獲取呢?BeginPaint函數(shù)的第二個(gè)參數(shù)就 是一個(gè)繪圖信息結(jié)構(gòu)的緩沖區(qū)地址,windows會(huì)在這里返回繪圖信息結(jié)構(gòu),結(jié)構(gòu)中包含了無(wú)效區(qū)域的位置和大小,繪圖信息結(jié)構(gòu)的定義如下:

typedef struct tagPAINTSTRUCT { // ps 
HDC   hdc; 
BOOL fErase; 
RECT rcPaint; 
BOOL fRestore; 
BOOL fIncUpdate; 
BYTE rgbReserved[32]; 
} PAINTSTRUCT; 

  其中hdc字段是窗口的設(shè)備環(huán)境句柄,rcPaint字段是一個(gè)RECT結(jié)構(gòu),它指定了無(wú)效區(qū)域矩形的對(duì)角頂點(diǎn) (如果開(kāi)始有一個(gè)((0,0),(40,40)),現(xiàn)在又來(lái)一個(gè)((20,20),(60,30)),那么拼接后就是((0,0), (60,40))),fErase字段如果為非零值,表示W(wǎng)indows在發(fā)送WM_PAINT消息前已經(jīng)使用背景色擦除了無(wú)效區(qū)域,后面3個(gè)字段是 Windows內(nèi)部使用的,應(yīng)用程序不必去理會(huì)他們。

  在某些情況下,顯示區(qū)域的一部分被臨時(shí)覆蓋,Windows試圖 保存一個(gè)顯示區(qū)域,并在以后恢復(fù)它,但這不一定能成功。Windows可能發(fā)送WM_PAINT消息:Windows 擦除覆蓋了部分窗口的對(duì)話(huà)框或消息框;菜單下拉出來(lái),然后被釋放;顯示工具提示消息。

  在某些情況下,Windows總是一定保存它所覆蓋的顯示區(qū)域,然后恢復(fù)它。這些情況是:鼠標(biāo)光標(biāo)穿越顯示區(qū)域;圖標(biāo)拖過(guò)顯示區(qū)域。

  有時(shí)候應(yīng)用也需要能夠主動(dòng)引發(fā)窗口中的繪制操作,比如當(dāng)窗口顯示的數(shù)據(jù)改變的時(shí)候,這一般是通過(guò) InvalidateRect和 InvalidateRgn函數(shù)來(lái)完成的。InvalidateRect和InvalidateRgn把指定的區(qū)域加到窗口的Update Region中,當(dāng)應(yīng)用的消息隊(duì)列沒(méi)有其他消息時(shí),如果窗口的Update Region不為空時(shí),系統(tǒng)就會(huì)自動(dòng)產(chǎn)生WM_PAINT消息。

  系統(tǒng)為什么不在調(diào)用Invalidate時(shí)發(fā)送WM_PAINT消息呢?又為什么非要等應(yīng)用消息隊(duì)列為空時(shí)才發(fā) 送WM_PAINT消息呢?這是因?yàn)橄到y(tǒng)把在窗口中的繪制操作當(dāng)作一種低優(yōu)先級(jí)的操作,于是盡 可能地推后做。不過(guò)這樣也有利于提高繪制的效率:兩個(gè)WM_PAINT消息之間通過(guò)InvalidateRect和InvaliateRgn使之失效的區(qū) 域就會(huì)被累加起來(lái),然后在一個(gè)WM_PAINT消息中一次得到 更新,不僅能避免多次重復(fù)地更新同一區(qū)域,也優(yōu)化了應(yīng)用的更新操作。像這種通過(guò)InvalidateRect和InvalidateRgn來(lái)使窗口區(qū)域無(wú) 效,依賴(lài)于系統(tǒng)在合適的時(shí)機(jī)發(fā)送WM_PAINT消息的機(jī) 制實(shí)際上是一種異步工作方式,也就是說(shuō),在無(wú)效化窗口區(qū)域和發(fā)送WM_PAINT消息之間是有延遲的;有時(shí)候這種延遲并不是我們希望的,這時(shí)我們當(dāng)然可以 在無(wú)效化窗口區(qū)域后利用SendMessage 發(fā)送一條WM_PAINT消息來(lái)強(qiáng)制立即重畫(huà),但不如使用Windows GDI為我們提供的更方便和強(qiáng)大的函數(shù):UpdateWindow和RedrawWindow。UpdateWindow會(huì)檢查窗口的Update Region,當(dāng)其不為空時(shí)才發(fā)送WM_PAINT消息;RedrawWindow則給我們更多的控制:是否重畫(huà)非客戶(hù)區(qū)和背景,是否總是發(fā)送 WM_PAINT消息而不管Update Region是否為空等。

  BeginPaint

  今天在處理WM_PAINT消息時(shí)產(chǎn)生了一個(gè)低級(jí)的錯(cuò)誤,并搞的我花了快一個(gè)小時(shí)才找到原因。我在處理消息時(shí), 沒(méi)有使用BeginPaint和EndPaint這對(duì)函數(shù),結(jié)果我其余的消息彈不出來(lái),窗口拖動(dòng)時(shí),不停閃爍(其實(shí)那就是重繪)。后來(lái)還是在MSDN上找 到了答案,現(xiàn)將原話(huà)貼出來(lái)。(在MSDN的The WM_PAINT Message標(biāo)題中)

  BeginPaint sets the update region of a window to NULL. This clears the region, preventing it fromgenerating subsequent WM_PAINT messages. If an application processes a WM_PAINT message but does not call BeginPaint or otherwise clear the update region, the application continues to receive WM_PAINT messages as long as the region is not empty. In all cases, an application must clear the update region before returning from the WM_PAINT message. 
BeginPaint函數(shù)的作用就是將窗口需要重繪的區(qū)域設(shè)置為空(也就是Update Region置空)。在正常情況下,我們接收到了WM_PAINT消息后,窗口的Update Region都是非空的(如果為空就不需要發(fā)送WM_PAINT消息了)。而當(dāng)你響應(yīng)這個(gè)消息的時(shí)候又不調(diào)用BeginPaint來(lái)清空,窗口的 Update Region就一直是非空的,系統(tǒng)就會(huì)一直發(fā)送WM_PAINT消息。這樣就形成了一個(gè)處理WM_PAINT消息的死循環(huán)。

  BeginPaint和WM_PAINT消息緊密相關(guān)。試一試在WM_PAINT處理函數(shù)中不寫(xiě) BeginPaint會(huì)怎樣?程序會(huì)像進(jìn)入了一個(gè)死循環(huán)一樣達(dá)到驚人的CPU占用率,你會(huì)發(fā)現(xiàn)程序總在處理一個(gè)接 一個(gè)的WM_PAINT消息。這是因?yàn)樵谕ǔG闆r下,當(dāng)應(yīng)用收到WM_PAINT消息時(shí),窗口的Update Region都是非空的(如果為空就不需要發(fā)送WM_PAINT消息了),BeginPaint的一個(gè)作用就是把該Update Region置為空,這樣如果不調(diào)用BeginPaint,窗口的Update Region就一直不為空,如前所述,系統(tǒng)就會(huì)一直發(fā)送WM_PAINT消息。

  BeginPaint和WM_ERASEBKGND消息也有關(guān)系。當(dāng)窗口的Update Region被標(biāo)志為需要擦除背景時(shí),BeginPaint會(huì)發(fā)送WM_ERASEBKGND消息來(lái)重畫(huà)背景,同時(shí)在其返回信息里有一個(gè)標(biāo)志表明窗口背景 是否被重畫(huà)過(guò)。當(dāng)我們用InvalidateRect和InvalidateRgn來(lái)把指定區(qū)域加到Update Region中時(shí),可以設(shè)置該區(qū)域是否需要被擦除背景,這樣下一個(gè)BeginPaint就知道是否需要發(fā)送WM_ERASEBKGND消息了。

  當(dāng)然關(guān)于 WM_PAINT消息還有很多的知識(shí)需要學(xué)習(xí)。另外要注意的一點(diǎn)是,BeginPaint只能在WM_PAINT處理函數(shù)中使用,并且在調(diào)用了 BeginPaint函數(shù)后,不要忘記了調(diào)用EndPaint函數(shù),他們可是一對(duì)的。

  重畫(huà) 函數(shù) InvalidateRect,Invalidate,UpdateWindow, RedrawWindow

  InvalidateRect(部分區(qū)域) 和Invalidate(整個(gè)窗口) 僅僅是用來(lái)設(shè)置無(wú)效區(qū)域,但是并不重繪窗口。

  UpdateWindow 檢查窗口有無(wú)無(wú)效區(qū)域,如果有,則立即發(fā)送一個(gè)WM_PAINT 消息給窗口并立即重畫(huà)。 

  RedrawWindow相當(dāng)于先調(diào)用InvalidateRect,緊接著又調(diào)用UpdateWindow, 此外RedrawWindow還提供了一些前兩者沒(méi)法做到的功能。

????? 如果不調(diào)用 InvalidateRect就調(diào)用 UpdateWindow,那么UpdateWindow什么都不做,因?yàn)闆](méi)有無(wú)效區(qū)域。如果調(diào)用 InvalidateRect 后不調(diào)用UpdateWindow,則系統(tǒng)會(huì)自動(dòng)在窗口消息隊(duì)列為空的時(shí)候,系統(tǒng)自動(dòng)發(fā)送一WM_PAINT消息。

與50位技術(shù)專(zhuān)家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的【转】VC窗口刷新InvalidateRect和UpdateWindow RedrawWindow的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 浮力影院国产第一页 | 性欧美free | 精品日本一区二区三区在线观看 | 在线观看福利电影 | 制服丝袜在线一区 | 亚洲影视一区二区 | 凹凸视频一区二区 | 免费看黄色片网站 | 亚洲日批 | 欧美丝袜脚交 | 性――交――性――乱a | 亚洲综合视频一区 | 国产亚洲激情 | 美日韩成人av | 好吊一区二区三区视频 | 男生和女生靠逼视频 | 久久精品视频免费 | 少妇精品一区二区三区 | 爱情岛亚洲品质自拍极速福利网站 | 日韩 欧美 综合 | 秘密基地免费观看完整版中文 | 国产一级二级 | 一区亚洲 | 国产精品情侣 | 69精品无码成人久久久久久 | 亚洲人成无码网站久久99热国产 | 日日躁夜夜躁狠狠久久av | 伊人激情在线 | 亚洲无打码 | 日韩久久精品视频 | 无码无遮挡又大又爽又黄的视频 | 国产精品熟女一区二区不卡 | 国产理论片 | 91精品播放 | 国产在线一级 | 自拍日韩亚洲一区在线 | 97人人精品| 免费看黄色的网址 | 美国性生活大片 | 亚洲欧美日韩在线看 | 色老二导航 | 老牛嫩草二区三区观影体验 | 91一区二区在线 | 国产精品一区二区性色av | 亚欧av在线| www激情com | 久久99久久98精品免观看软件 | 在线观看jizz | 久久久精品美女 | 韩国一级淫片 | 69精品久久久久久久 | 中文字幕高清在线 | 91综合视频 | 台湾男男gay做爽爽的视频 | 91青青草视频 | 91看片网页版 | 成人毛片在线精品国产 | 黄色一级免费 | 操女人逼逼视频 | sese视频在线观看 | 亚洲综合色一区 | 国产不卡在线观看视频 | 精品人妻一区二区三区四区在线 | 日韩一级视频 | 国产乱淫av麻豆国产免费 | 极品探花在线播放 | 欧美一区二区三区久久久 | 性感美女福利视频 | 色妺妺视频网 | 欧美成人精品欧美一级乱 | 在线观看免费观看在线 | 特大黑人巨人吊xxxx | 97超碰在线免费观看 | 久久精品视频6 | 成人精品毛片 | 国产精品免费无遮挡无码永久视频 | 少妇闺蜜换浪荡h肉辣文 | 香蕉视频性 | 国产交换配乱淫视频免费 | 久久久久久综合网 | 国产精品suv一区二区88 | 亚洲a在线视频 | 手机看片亚洲 | 朴麦妮原版视频高清资源 | 一级二级av| 成人免费毛片东京热 | 午夜羞羞羞| 欧美a级黄色片 | 精品无码m3u8在线观看 | 久久综合区 | 国产精品交换 | 黄色激情小说视频 | 在线永久看片免费的视频 | 亚洲欧美日韩色 | 久久久久久香蕉 | 善良的老师伦理bd中字 | 91大神视频在线播放 | 超碰人人搞| 桥本有菜aⅴ一区二区三区 在线午夜电影 |