• 首页
  • 粮食
  • 蔬菜
  • 果品
  • 综合
  • 酒水
  • 饮料
  • 茶叶
  • 畜禽
  • 食用油
  • 资讯
logo
  • 首页>
  • 综合 >
  • 正文

浅谈 CS_OWNDC 标志位的作用,你学会了吗?

2023-08-30 09:11:12 来源:今日头条

关于设备上下文(Device Context, 简称 DC) ,我想到这样一个原则:大多数情况下,窗口 DC 只是作为临时使用。

例如,如果你想在窗口中绘制些什么东西,你可以在 WM_PAINT 消息到来的时候,调用 BeginPaint,或者在其他时间点,调用 GetDC,但我们通常还是建议将绘制工作尽可能地放在 WM_PAINT 消息处理代码中。


(相关资料图)

当你调用上面说的两个函数后,窗口管理器会产生一个窗口对应的 DC 并返回给你。然后,你可以使用这个 DC 进行绘制,当绘制结束的时候,通过调用 EndPaint 或者 ReleaseDC,我们将 DC 恢复它原本的状态并返回给窗口管理器。

从内部实现的角度来看,窗口管理器保留了一小段 DC 缓存,当人们请求窗口 DC 时,它会读取该缓存,当 DC 返回时,它会返回到缓存中。由于窗口 DC 只是临时使用的,因此未完成使用的 DC 的数量通常不是很多,并且小型缓存足以满足正常运行系统中的 DC 需求。

如果注册窗口类并在类样式中包含 CS_OWNDC 标志,则窗口管理器将为窗口创建一个 DC,并使用特殊标记将其放入 DC 缓存中,该标记表示: “不要从 DC 缓存中清除此 DC,因为它是此窗口的 CS_OWNDC “。如果调用 BeginPaint 或 GetDC 来获取CS_OWNDC窗口的 DC,则始终会找到并返回该 DC(因为它被标记为“从不清除”)。这样做的后果有好有坏。

好的一方面是:由于 DC 是专门为窗口创建的并且永远不会被清除,因此你不必担心在将其返回到缓存之前会被清理掉。每当你调用 BeginPaint 或 GetDC 以获取CS_OWNDC窗口时,你总是会得到那个特殊的 DC。事实上,这就是 CS_OWNDC 窗口的全部意义:你可以创建一个 CS_OWNDC 窗口,获取其 DC,按照你喜欢的方式进行设置(选择字体、设置颜色等),即使你释放 DC 并稍后再次获取它,你也会得到相同的 DC,它将是你离开它的方式。

坏的一方面是:你正在获取本来应该暂时使用的东西(窗口 DC)并永久使用它。早期版本的 Windows 对 DC 的限制非常低(八个左右),因此在不需要 DC 时立即释放它们至关重要。自那时以来,这一限额已大幅提高,但基本原则仍然是:应该小心谨慎的使用 DC 并尽可能早地归还给窗口管理器。你可能已经注意到,CS_OWNDC 的实现仍然使用 DC 缓存,只是这些 DC 有一个特殊的标记,所以 DC 管理器知道要特别对待它们。这意味着大量 CS_OWNDC DC 最终会”污染” DC 缓存,从而减慢未来对需要搜索 DC 缓存的函数(如 BeginPaint 和 ReleaseDC)的调用。

(为什么DC 管理器不优化处理大量 CS_OWNDC DC 的情况?首先,正如我已经指出的,最初的 DC 管理器不必担心大量 DC 的情况,因为系统一开始甚至无法创建那么多 DC。其次,即使在提高了对 DC 数量的限制之后,重写 DC 管理器以优化 CS_OWNDC DC 的处理也没有多大意义,因为程序员已经被告知要谨慎使用 CS_OWNDC 。这是软件工程的实用性之一:你只能做这么多。你决定做的一切都是以牺牲其他东西为代价的。很难证明优化程序员被告知要避免的场景是合理的,而事实上他们已经在避免这种情况。你不会针对有人滥用你的系统的情况进行优化。这就像,花时间设计汽车的发动机,以便在汽车没有机油的情况下保持良好的油耗。)

更糟糕的是,大多数窗口框架库和几乎所有示例代码都假定你的窗口不是 CS_OWNDC 窗口。请考虑以下代码,该代码以两种字体绘制文本,使用第一种字体来指定字符在第二种字体中的位置。它看起来很好,不是吗?

我们得到两个用于窗口的 DC。首先,我们选择第一种字体;在第二个中,我们选择第二个。在第一个 DC 中,我们还将文本对齐方式设置为 TA_UPDATECP 这意味着传递给 TextOut 函数的坐标将被忽略。相反,文本将从“当前位置”开始绘制,“当前位置”将更新到字符串的末尾,以便对 TextOut 的下一次调用将从上一个调用中断的地方继续。

设置两个 DC 后,我们一次绘制一个字符的字符串。我们在第一个 DC 中查询当前位置,并以相同的 x 坐标(但略低)绘制第二种字体中的字符,然后以第一种字体绘制字符(这也推进当前位置)。

文本绘制循环完成后,我们将还原两个 DC 的状态,作为标准绘制流程的一部分。该函数的目的是绘制类似这样的内容,其中第一个字体大于第二个字体。

如果窗口没有设置 CS_OWNDC,则结果就是你想要的了。你可以通过从我们的临时程序中调用它。

但是,如果窗口设置了 CS_OWNDC,那么坏事就会发生。你可以将 wc.style = 0 修改成 wc.style = CS_OWNDC,你就会看到这样的效果:

当然,如果你了解 CS_OWNDC 的工作原理,这根本不出乎意料。理解的关键是:当窗口设置了 CS_OWNDC 时,无论你调用多少次,GetDC 都会返回相同的 DC。现在你所要做的就是查看 FunnyDraw 函数,并记住 hdc1 和 hdc2 实际上是一回事。

到目前为止,函数的执行是很正常的。

HDC hdc2 = GetDC(hwnd);

由于该窗口是 CS_OWNDC 窗口,因此在 hdc2 中返回的 DC 与在 hdc1 中返回的 DC 相同。换句话说,hdc1 == hdc2!现在事情变得令人兴奋了。

HFONT hfPrev2 = SelectFont(hdc2, hf2);

由于 hdc1 == hdc2,这真正做的是从 DC 中取消选择字体 hf1 并选择字体 hf2。

现在这个循环完全崩溃了。在第一次迭代中,我们从 DC 检索当前位置,它返回 (0, 0),因为我们还没有移动它。然后,我们将位置 (0, 30) 处的字母“H”绘制到第二个 DC 中。但由于第二个 DC 与第一个 DC 相同,因此真正发生的是我们将 TextOut 调用到处于 TA_UPDATECP 模式的 DC。因此,坐标被忽略,显示字母“H”(以第二种字体),并将当前位置更新为“H”之后。最后,我们将“H”绘制到第一个 DC(与第二个相同)。我们认为我们用第一种字体绘制它,但实际上我们用第二种字体绘制。我们认为我们在 (0, 0) 处绘制,但实际上我们在 (x, 0) 处绘制,其中 x 是字母“H”的宽度,因为对 TextOut(hdc2, …) 的调用更新了当前位置。

因此,每次通过循环时,字符串中的下一个字符都会显示两次,全部以第二种字体显示。

但是等等,灾难还没有结束。看看我们的清理代码:

SelectFont(hdc1, hfPrev1);

这会将原始字体还原到 DC 中。

SelectFont(hdc2, hfPrev2);

这将重新选择第一个字体!我们未能将 DC 还原到其原始状态,最终将“损坏”的 DC 放入缓存中。

这就是为什么我将 CS_OWNDC 描述为“更糟”。它采用过去有效的代码,并通过违反大多数人对 DC 做出的假设(通常没有意识到)来破坏它。

如果你觉得 CS_OWNDC 很糟糕了,没事,还有更糟的,下次我会谈谈被称为 CS_CLASSDC 的灾难。

总结

对于自己不了解的东西,要小心谨慎的尝试,决不能先入为主。像一个婴儿一样对待所有新生事物,正所谓:一叶障目也。

关键词:

    为您推荐

  • 商务部:上周食用农产品价格上涨4.3% 猪肉批发价涨9.7%

    资讯2021-10-27
  • 商务部:上周生产资料价格上涨5% 煤炭继续领涨

    资讯2021-10-27
  • 美术作品中的党史 | 第61集《1978年11月24日·小岗》

    资讯2021-10-27
  • 31省份累计报告接种新冠病毒疫苗224868.8万剂次

    资讯2021-10-27
  • 草原都市呼和浩特战疫记:民众做好防控,生活未受冲击

    资讯2021-10-27
  • 恭城:做大做强地理标志产品,“农旅融合”助推乡村振兴

    资讯2021-10-27
  • 安徽:5年来追回外逃人员183人

    资讯2021-10-27
  • 第十三届中国舞蹈“荷花奖”民族民间舞评奖活动开幕

    资讯2021-10-27
  • 甘肃兰州统一安排中小学线上教学 各学校“停课不停学”

    资讯2021-10-27
  • 内蒙古包头发生多车连撞事故 已致5死11伤

    资讯2021-10-27
  • 商务部:上周猪肉消费明显回升 零售价格止跌上扬

    资讯2021-10-27
  • 全方位提高供给质量 推动食品产业高质量发展

    资讯2021-10-27
  • 坚持“六大保障” 构建超大城市食品安全社会共治新格局

    资讯2021-10-27
  • 17部门联合发文 推进国家文化出口基地提质扩容增效

    资讯2021-10-27
  • 俄卡马河畔切尔尼市一住宅楼天然气爆炸 5人伤亡

    资讯2021-10-27
  • 国家中小企业发展基金与全国股转公司、北交所签署战略合作协议

    资讯2021-10-27
  • 网易云课堂引进亚马逊AWS近百门IT类课程 向社会免费开放

    资讯2021-10-27
  • 冰雪之约 中国之邀|北京冬奥会倒计时100天,我们准备好了!

    粮食2021-10-27
  • 第38届和第39届东盟峰会在文莱开幕

    粮食2021-10-27
  • 高德车道级导航正式发布 覆盖全国超120个城市高速和快速路

    粮食2021-10-27

果品

  • 北京2022年冬奥会、冬残奥会奖牌“同心”正式发布
  • 冬奥故事会丨一图了解冬奥会历届奖牌
  • 同心筑梦向未来——写在北京冬奥会开幕倒计时100天之际
  • 外交部:美国针对亚裔仇恨犯罪数字令人痛心

蔬菜

  • 说好“一梯一户”却成了“两梯两户”,买方能否解除合同?
  • 更高水平开放合作助力中国东盟经贸发展迎新机遇
  • 9被告人犯侵犯著作权罪被判刑罚
  • 玉渊谭天丨中美再通话,“建设性”很重要
  • 环球时报社评:中美经贸需要建设性对话
  • 俄媒:莫斯科扩大新冠感染新疗法试点范围
  • 冰雪之约 中国之邀 | 追赶的勇气
  • 中国第20批赴黎维和建筑工兵分队完成“VA-2”道路排水系统修缮任务
  • 中国常驻联合国代表团举办恢复联合国合法席位50周年图片展
  • 美专家认为三大原因导致美国供应链危机

大河食品网 大河食品网 版权所有 联系邮箱:435 226 40@qq.com 备案号:京ICP备2022022245号-75

Copyright ? 1998-2015 by www.shipin.hzdx.com all rights reserved