成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺談 CS_OWNDC 標(biāo)志位的作用,你學(xué)會(huì)了嗎?

開發(fā) 前端
當(dāng)你調(diào)用上面說的兩個(gè)函數(shù)后,窗口管理器會(huì)產(chǎn)生一個(gè)窗口對應(yīng)的 DC 并返回給你。然后,你可以使用這個(gè) DC 進(jìn)行繪制,當(dāng)繪制結(jié)束的時(shí)候,通過調(diào)用 EndPaint 或者 ReleaseDC,我們將 DC 恢復(fù)它原本的狀態(tài)并返回給窗口管理器。

關(guān)于設(shè)備上下文(Device Context, 簡稱 DC) ,我想到這樣一個(gè)原則:大多數(shù)情況下,窗口 DC 只是作為臨時(shí)使用。

例如,如果你想在窗口中繪制些什么東西,你可以在 WM_PAINT 消息到來的時(shí)候,調(diào)用 BeginPaint,或者在其他時(shí)間點(diǎn),調(diào)用 GetDC,但我們通常還是建議將繪制工作盡可能地放在 WM_PAINT 消息處理代碼中。

當(dāng)你調(diào)用上面說的兩個(gè)函數(shù)后,窗口管理器會(huì)產(chǎn)生一個(gè)窗口對應(yīng)的 DC 并返回給你。然后,你可以使用這個(gè) DC 進(jìn)行繪制,當(dāng)繪制結(jié)束的時(shí)候,通過調(diào)用 EndPaint 或者 ReleaseDC,我們將 DC 恢復(fù)它原本的狀態(tài)并返回給窗口管理器。

從內(nèi)部實(shí)現(xiàn)的角度來看,窗口管理器保留了一小段 DC 緩存,當(dāng)人們請求窗口 DC 時(shí),它會(huì)讀取該緩存,當(dāng) DC 返回時(shí),它會(huì)返回到緩存中。由于窗口 DC 只是臨時(shí)使用的,因此未完成使用的 DC 的數(shù)量通常不是很多,并且小型緩存足以滿足正常運(yùn)行系統(tǒng)中的 DC 需求。

如果注冊窗口類并在類樣式中包含 CS_OWNDC 標(biāo)志,則窗口管理器將為窗口創(chuàng)建一個(gè) DC,并使用特殊標(biāo)記將其放入 DC 緩存中,該標(biāo)記表示: “不要從 DC 緩存中清除此 DC,因?yàn)樗谴舜翱诘?CS_OWNDC “。如果調(diào)用 BeginPaint 或 GetDC 來獲取CS_OWNDC窗口的 DC,則始終會(huì)找到并返回該 DC(因?yàn)樗粯?biāo)記為“從不清除”)。這樣做的后果有好有壞。

好的一方面是:由于 DC 是專門為窗口創(chuàng)建的并且永遠(yuǎn)不會(huì)被清除,因此你不必?fù)?dān)心在將其返回到緩存之前會(huì)被清理掉。每當(dāng)你調(diào)用 BeginPaint 或 GetDC 以獲取CS_OWNDC窗口時(shí),你總是會(huì)得到那個(gè)特殊的 DC。事實(shí)上,這就是 CS_OWNDC 窗口的全部意義:你可以創(chuàng)建一個(gè) CS_OWNDC 窗口,獲取其 DC,按照你喜歡的方式進(jìn)行設(shè)置(選擇字體、設(shè)置顏色等),即使你釋放 DC 并稍后再次獲取它,你也會(huì)得到相同的 DC,它將是你離開它的方式。

壞的一方面是:你正在獲取本來應(yīng)該暫時(shí)使用的東西(窗口 DC)并永久使用它。早期版本的 Windows 對 DC 的限制非常低(八個(gè)左右),因此在不需要 DC 時(shí)立即釋放它們至關(guān)重要。自那時(shí)以來,這一限額已大幅提高,但基本原則仍然是:應(yīng)該小心謹(jǐn)慎的使用 DC 并盡可能早地歸還給窗口管理器。你可能已經(jīng)注意到,CS_OWNDC 的實(shí)現(xiàn)仍然使用 DC 緩存,只是這些 DC 有一個(gè)特殊的標(biāo)記,所以 DC 管理器知道要特別對待它們。這意味著大量 CS_OWNDC DC 最終會(huì)”污染” DC 緩存,從而減慢未來對需要搜索 DC 緩存的函數(shù)(如 BeginPaint 和 ReleaseDC)的調(diào)用。

(為什么DC 管理器不優(yōu)化處理大量 CS_OWNDC DC 的情況?首先,正如我已經(jīng)指出的,最初的 DC 管理器不必?fù)?dān)心大量 DC 的情況,因?yàn)橄到y(tǒng)一開始甚至無法創(chuàng)建那么多 DC。其次,即使在提高了對 DC 數(shù)量的限制之后,重寫 DC 管理器以優(yōu)化 CS_OWNDC DC 的處理也沒有多大意義,因?yàn)槌绦騿T已經(jīng)被告知要謹(jǐn)慎使用 CS_OWNDC 。這是軟件工程的實(shí)用性之一:你只能做這么多。你決定做的一切都是以犧牲其他東西為代價(jià)的。很難證明優(yōu)化程序員被告知要避免的場景是合理的,而事實(shí)上他們已經(jīng)在避免這種情況。你不會(huì)針對有人濫用你的系統(tǒng)的情況進(jìn)行優(yōu)化。這就像,花時(shí)間設(shè)計(jì)汽車的發(fā)動(dòng)機(jī),以便在汽車沒有機(jī)油的情況下保持良好的油耗。)

更糟糕的是,大多數(shù)窗口框架庫和幾乎所有示例代碼都假定你的窗口不是 CS_OWNDC 窗口。
請考慮以下代碼,該代碼以兩種字體繪制文本,使用第一種字體來指定字符在第二種字體中的位置。它看起來很好,不是嗎?

我們得到兩個(gè)用于窗口的 DC。首先,我們選擇第一種字體;在第二個(gè)中,我們選擇第二個(gè)。在第一個(gè) DC 中,我們還將文本對齊方式設(shè)置為 TA_UPDATECP 這意味著傳遞給 TextOut 函數(shù)的坐標(biāo)將被忽略。相反,文本將從“當(dāng)前位置”開始繪制,“當(dāng)前位置”將更新到字符串的末尾,以便對 TextOut 的下一次調(diào)用將從上一個(gè)調(diào)用中斷的地方繼續(xù)。

設(shè)置兩個(gè) DC 后,我們一次繪制一個(gè)字符的字符串。我們在第一個(gè) DC 中查詢當(dāng)前位置,并以相同的 x 坐標(biāo)(但略低)繪制第二種字體中的字符,然后以第一種字體繪制字符(這也推進(jìn)當(dāng)前位置)。

文本繪制循環(huán)完成后,我們將還原兩個(gè) DC 的狀態(tài),作為標(biāo)準(zhǔn)繪制流程的一部分。
該函數(shù)的目的是繪制類似這樣的內(nèi)容,其中第一個(gè)字體大于第二個(gè)字體。

如果窗口沒有設(shè)置 CS_OWNDC,則結(jié)果就是你想要的了。你可以通過從我們的臨時(shí)程序中調(diào)用它。

但是,如果窗口設(shè)置了 CS_OWNDC,那么壞事就會(huì)發(fā)生。你可以將 wc.style = 0 修改成 wc.style = CS_OWNDC,你就會(huì)看到這樣的效果:

當(dāng)然,如果你了解 CS_OWNDC 的工作原理,這根本不出乎意料。理解的關(guān)鍵是:當(dāng)窗口設(shè)置了 CS_OWNDC 時(shí),無論你調(diào)用多少次,GetDC 都會(huì)返回相同的 DC。現(xiàn)在你所要做的就是查看 FunnyDraw 函數(shù),并記住 hdc1 和 hdc2 實(shí)際上是一回事。

到目前為止,函數(shù)的執(zhí)行是很正常的。

HDC hdc2 = GetDC(hwnd);

由于該窗口是 CS_OWNDC 窗口,因此在 hdc2 中返回的 DC 與在 hdc1 中返回的 DC 相同。換句話說,hdc1 == hdc2!現(xiàn)在事情變得令人興奮了。

HFONT hfPrev2 = SelectFont(hdc2, hf2);

由于 hdc1 == hdc2,這真正做的是從 DC 中取消選擇字體 hf1 并選擇字體 hf2。

現(xiàn)在這個(gè)循環(huán)完全崩潰了。在第一次迭代中,我們從 DC 檢索當(dāng)前位置,它返回 (0, 0),因?yàn)槲覀冞€沒有移動(dòng)它。然后,我們將位置 (0, 30) 處的字母“H”繪制到第二個(gè) DC 中。但由于第二個(gè) DC 與第一個(gè) DC 相同,因此真正發(fā)生的是我們將 TextOut 調(diào)用到處于 TA_UPDATECP 模式的 DC。因此,坐標(biāo)被忽略,顯示字母“H”(以第二種字體),并將當(dāng)前位置更新為“H”之后。最后,我們將“H”繪制到第一個(gè) DC(與第二個(gè)相同)。我們認(rèn)為我們用第一種字體繪制它,但實(shí)際上我們用第二種字體繪制。我們認(rèn)為我們在 (0, 0) 處繪制,但實(shí)際上我們在 (x, 0) 處繪制,其中 x 是字母“H”的寬度,因?yàn)閷?TextOut(hdc2, …) 的調(diào)用更新了當(dāng)前位置。

因此,每次通過循環(huán)時(shí),字符串中的下一個(gè)字符都會(huì)顯示兩次,全部以第二種字體顯示。

但是等等,災(zāi)難還沒有結(jié)束。看看我們的清理代碼:

SelectFont(hdc1, hfPrev1);

這會(huì)將原始字體還原到 DC 中。

SelectFont(hdc2, hfPrev2);

這將重新選擇第一個(gè)字體!我們未能將 DC 還原到其原始狀態(tài),最終將“損壞”的 DC 放入緩存中。

這就是為什么我將 CS_OWNDC 描述為“更糟”。它采用過去有效的代碼,并通過違反大多數(shù)人對 DC 做出的假設(shè)(通常沒有意識到)來破壞它。

如果你覺得 CS_OWNDC 很糟糕了,沒事,還有更糟的,下次我會(huì)談?wù)劚环Q為 CS_CLASSDC 的災(zāi)難。

總結(jié)

對于自己不了解的東西,要小心謹(jǐn)慎的嘗試,決不能先入為主。
像一個(gè)嬰兒一樣對待所有新生事物,正所謂:一葉障目也。

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2023-01-10 08:43:15

定義DDD架構(gòu)

2024-02-28 09:07:58

鏈路聚合模式

2023-08-30 07:25:20

Windows協(xié)作式DC

2022-04-29 08:55:43

前端開發(fā)規(guī)范

2022-12-07 10:17:32

WindowsANSI

2023-01-13 16:46:38

CRM系統(tǒng)建設(shè)

2024-05-30 09:43:00

2022-07-08 09:27:48

CSSIFC模型

2024-01-19 08:25:38

死鎖Java通信

2024-02-04 00:00:00

Effect數(shù)據(jù)組件

2023-07-26 13:11:21

ChatGPT平臺工具

2024-02-02 11:03:11

React數(shù)據(jù)Ref

2023-08-01 12:51:18

WebGPT機(jī)器學(xué)習(xí)模型

2024-01-02 12:05:26

Java并發(fā)編程

2023-10-10 11:04:11

Rust難點(diǎn)內(nèi)存

2024-05-06 00:00:00

InnoDBView隔離

2023-01-30 09:01:54

圖表指南圖形化

2024-07-31 08:39:45

Git命令暫存區(qū)

2023-12-12 08:02:10

2024-08-06 09:47:57

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产视频h | 午夜精品久久久久久久久久久久久 | 一区二区三区国产 | 亚洲一区免费在线 | 亚洲精选久久 | 亚洲欧美精品 | 久草综合在线 | 久久一二区 | 免费黄视频网站 | 国精品一区 | 成人在线一区二区 | 51ⅴ精品国产91久久久久久 | 午夜视频免费在线观看 | 天天爽天天操 | 亚洲一区电影 | 免费一级黄色录像 | 福利影院在线看 | 在线观看涩涩视频 | 国产视频一区在线 | 超碰成人免费 | 亚洲精品久久区二区三区蜜桃臀 | 欧美日韩亚洲成人 | 国产精品视频在线观看 | 精品真实国产乱文在线 | 日韩精品一二三 | 九色在线 | 精品伊人久久 | 亚洲一区视频 | 日本精品视频 | 黄色大片视频 | 欧美videosex性极品hd | 午夜久久| 欧美成人精品欧美一级 | 亚洲欧美日韩国产综合 | 国产精品欧美一区二区三区不卡 | 日本欧美国产在线 | 欧美精品一区二区在线观看 | 国产精品视频网站 | 亚洲国产小视频 | 午夜精品影院 | 在线一区|