CS_SAVEBITS 这个样式有什么作用?

CS_SAVEBITS 这个样式有什么作用?

作者:BlogUpdater |  时间:2023-07-29 |  浏览:621 |  评论已关闭 条评论

简单来说,如果你在创建窗口的时候在窗口类中指定了 CS_SAVEBITS 标志,则窗口管理器会尝试保存此窗口所遮盖的区域的位图数据。

但是,这里比较关键的问题是:为什么要这样做?只有明白了这其中的原理,你才会在正确的场合使用它,而不是滥用。

当一个指定了 CS_SAVEBITS 标志的窗口显示在屏幕上时,窗口管理器会保存窗口即将显示的屏幕区域的位图数据。首先,它会要求显卡保存这些位图数据到显存中(这种方式很快)。如果当前没有显存空间可用,则位图数据将会保存到系统内存(这种方式较慢)。如果与此同时,保存的数据没有被丢弃(见下文),则当窗口隐藏的时候,被保存的数据将会恢复到窗口的显示位置并标记为”有效”,换句话说,系统将不会为这个区域产生 WM_PAINT 消息。

在何种情况下会将这个数据标记为无效呢?当窗口隐藏后,会导致这个数据和屏幕上应该显示的内容不同步的任何内容。(好好理解,这里会有点绕哈)
下面是一些例子:

> 如果窗口是一个弹出式窗口且移动了,则保存的数据将会被丢弃,因为如果将这些数据恢复到屏幕上,将会显示错误的图像。

> 如果窗口通过调用 InvalidateRect 将其本身无效化,则保存的数据也会被丢弃,因为窗口已经暗示了它希望修改它的显示内容。

> 如果弹出窗口下方的任何窗口更改大小或位置或 Z 序,则保存的数据也没有用。

> 如果在弹出窗口下方创建或销毁了任何窗口。

> 如果有人调用 GetDC 在弹出窗口下方的窗口并开始绘制。

至此,你应该有点感觉了。
如果将保存的数据复制回屏幕会导致显示的不一致,则会丢弃保存的数据。

知道了原理,下面我们来探讨如何正确的使用这个标志。

一个注意事项是,该区域应覆盖屏幕的相对较小的部分,因为保存的位图越大,它适合可用的屏幕外显存的可能性就越小,这意味着它更有可能在显存到系统内存的位传输过程中穿越总线,这是游戏开发人员非常熟悉的可怕的所谓的 “显存到内存传输”。

在显存内存间传输的宏伟计划中,”显存到显存”是最快的(因为显卡非常擅长在自身内部移动内存),”内存到内存”是第二快的(因为主板可以在自身内部打乱内存,尽管它会花费你的CPU缓存空间),”内存到显存”排在第三位,而”显存到内存”是性能最差的:程序写入显存的频率比从中读取的频率要高得多。因此,显卡和系统内存之间的带宽针对写入显存而不是从读取显存做了优化。

但是,决定何时使用 CS_SAVEBITS 窗口类样式的主要关注点并不是让窗口管理器费尽心思保存像素,只是不得不扔掉它们。

因此,适合 CS_SAVEBITS 样式的窗口是不移动的窗口,覆盖屏幕的相对较小的部分,并且仅在短时间内可见。窗口不应该移动是显而易见的:如果窗口移动,那么保存的像素就没有用了。其他两个经验法则试图尽量减少另一个窗口执行使保存的像素无效的操作的机会。通过保持窗口面积小并将其放在屏幕上很短的时间,你可以在空间和时间上保持”目标”较小。

因此,CS_SAVEBITS 的最佳候选对象是菜单、工具提示和小对话框,因为它们不是太大,它们通常不会四处移动,而且它们很快就会消失。

有些人似乎错误地认为 CS_SAVEBITS 保存了窗口本身的部分。我不知道人们从哪里得到这种印象,因为即使是做一个小实验也很容易证明它是错误的。Windows 绘图模型遵循一个简单原则:不保存任何可以重新计算的内容。

总结
记住一点,仅在这些窗口上使用 CS_SAVEBITS : 菜单、工具提示和小的对话框。
亲爱的你,记住了吗?

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《What does CS_SAVEBITS do?》

最近我写了个东西
正如你们所知道的,拓扑梅尔智慧办公平台(Topomel Box)是一款绿色软件,主要面向经常使用电脑的朋友。它提供了各种提升办公效率的小功能,同时操作上尽可能地简单方便。
我想:你值得拥有。

评论已关闭。