【问题标题】:Does CClientDC guarantee restoring the DC back to its previous state?CClientDC 是否保证将 DC 恢复到以前的状态?
【发布时间】:2017-11-05 07:06:51
【问题描述】:

我正在使用CClientDC 对象,它用作GetDC 和ReleaseDC 函数的包装器:

  • 从CClientDC 构造函数内部调用函数GetDC
  • 从CClientDC析构函数内部调用函数ReleaseDC

在这期间,我操作 DC(更换钢笔、画笔等)。

但我很确定 CClientDC 对象不会将 DC 恢复到之前的状态。

这意味着我必须自己确认。对吗?

谢谢。

【问题讨论】:

  • 是的。不过,目前尚不清楚您要完成什么(鉴于您的问题历史)。为什么不简单地遵循既定规则?
  • @IInspectable:我试图避免在我的代码中的几个OnPaint 处理程序中调用GetDC、ReleaseDC、SaveDC 和RestoreDC。 CClientDC 类帮助我完成前两个。我希望有一个基础设施来帮助我与其他人。目前,我最终写了一个小class CAppDC : public CClientDC。
  • 你应该在OnPaint处理程序中使用CPaintDC,而不是CClientDC!

标签: winapi mfc gdi


【解决方案1】:

从MFC源代码中打开wingdi.cpp,寻找CClientDC的实现:

CClientDC::~CClientDC()
{
    ASSERT(m_hDC != NULL);
    ::ReleaseDC(m_hWnd, Detach());
}

你看到它只调用ReleaseDC,这不将DC恢复到之前的状态。 CClientDC 无法知道您更改了哪些 GDI 对象。

如果你想保存和恢复 DC 的状态,有一些特殊的方法:CDC::SaveDC 和 CDC::RestoreDC。这些不是从CDC 或CClientDC 自动调用的——您需要自己手动调用它们。

或者,您可以保存和恢复您修改的每个单独的 GDI 对象。当您调用SelectObject 时,将返回原始对象。您保存它,并在取消选择您正在使用的对象时恢复它。

【讨论】:

  • 谢谢。 1.“从 MFC 源代码打开wingdi.cpp”——这正是我所做的(尽管通过调试器的单步执行)。这就是我写“我很确定”的原因(尽管我想我本可以选择一种更好的方式来表达)。 2. “CClientDC 无法知道您更改了哪些 GDI 对象。” - 是的,这对我来说也很明显。我一直想知道为什么包装类不简单地调用SaveDC 和RestoreDC。我最终写了一个小的class CAppDC : public CClientDC 来做到这一点。但我想知道为什么这个基础设施还不可行。
  • @goodvibration:因为系统没有针对不常见的情况进行优化。常见的情况是:应用程序知道何时需要恢复初始状态,以及如何恢复。 MFC 没有。您已经知道 CS_OWNDC 样式,所以这不足为奇。
  • C++ 的一般理念是你不应该为你不需要的东西买单。在编写很多的Windows代码时,我只需要SaveDC/RestoreDC一次。那么,为什么要将保存和恢复的开销强加给 DC 的 所有 用户呢? @好
  • 另外,虽然CClientDC::SelectObject() 记住它对每种对象类型的第一次调用并仅撤消析构函数中更改的对象类型可能是有意义的(以避免自己忘记这样做的常见错误),但是 a) 如果 MFC 被设计为实际上对程序员隐藏工作或只是为了 C++ 化现有工作,则 IDK,并且 b) 仍然会与 CS_OWNDC、sometimes with hilarious results 中断。
  • @andlabs:CDC 派生类实现了operator HDC(),并有一个public m_hDC 类成员。两者都允许回避CDC::SelectObject 实现并直接调用::SelectObject。到那时,CDC 实现是否尝试恢复其初始状态都没有实际意义,因为无法保证它甚至可以(通过监视每个图形对象的第一个 SelectObject 调用)。
猜你喜欢
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
  • 2011-06-27
  • 2011-10-21
  • 1970-01-01
  • 2017-09-15
  • 2018-12-01
相关资源
最近更新 更多