正确使用 Win32 设备上下文

Posted

技术标签:

【中文标题】正确使用 Win32 设备上下文【英文标题】:Proper use of Win32 Device Context 【发布时间】:2021-01-02 20:18:03 【问题描述】:

我已经使用 GDI 有一段时间了,我正在努力加深对它的理解,以便能够为它创建一个包装类。

    为什么在应用程序结束之前我不能保持窗口设备上下文?它是否会因任何事件而失效?我听到有人说在 WM_SIZE 之后上下文变得无效,这是真的吗?即使我总是缓存窗口上下文,我也从未经历过这种情况。它使得在构造函数中创建CompatibleDC()s 和createCompatibleBitmaps()s 变得更加容易。我还缓存了这些创建的 DC 并使用它们来避免闪烁,对于局部边界绘制,缓存绘制操作以防窗口最小化然后最大化。

    为什么应用程序一次会获取超过 1 个窗口上下文?由于文档抱怨用完窗口上下文限制。

【问题讨论】:

关于您的第二个问题,例如,您可以使用一个 DC 来绘制,然后将其 blit 到窗口 DC。这样可以防止直接在窗口 DC 上绘图时出现闪烁。 取决于如何创建 DC。如果你从 BeginPaint() 得到它,那么你会后悔缓存它,剪辑区域很容易变得陈旧。 GetDC() 没问题。如果创建对象很昂贵但存储很便宜,则缓存很有用。窗口 DC 的创建成本很低,但存储在非常有限的桌面堆中。只缓存一个无需担心。 @Hans 我没有缓存或使用多个窗口上下文的习惯,但是在我的系统变慢之前多少?我意外地发现,不断地创建位图而不释放会非常显着地减慢您的应用程序的速度。这意味着位图的内存非常昂贵。 @某程序员老兄,我的第二个问题完全是关于window dc而不是memory dc。 【参考方案1】:

请记住,在您谈论的上下文中,“无效”意味着需要重新绘制窗口的某些部分,这并不意味着从 GetDC 检索到的句柄将变得不可用。

具有 CS_HREDRAW 或 CS_VREDRAW 的窗口在指定方向上的任何调整大小以及任何增加窗口大小的调整操作都需要至少部分重绘。

由于 GDI 对象数量的限制,正常模式是处理 WM_PAINT 消息并使用 BeginPaint 返回的句柄(只有在未调用 EndPaint 时才会保持可用)。

正如一些程序员老兄在评论中所说,可以使用第二个 DC 来执行无闪烁绘图,耗时的绘图是在屏幕外 DC 上完成的,然后简单地复制到屏幕 DC 上。即使这完全在 WM_PAINT 处理程序中完成,一旦绘图操作完成,屏幕外 DC 通常也会被释放,以免占用 GDI 资源。

【讨论】:

太棒了。已确认窗口 dc 在我缓存时不会隐式失效。编程图形是速度与内存使用的妥协。您是说创建内存 dc 并获得窗口 dc 的速度足够快,而存储/占用资源的后果要糟糕得多?还有第二个问题。 open gl 或 directx 图形对象是否像 gdi 一样占用内存?我已经知道 opengl 上下文是从 gdi 上下文派生的。 似乎这应该是一个新问题,我不知道答案。我是盲人并使用 GDI,因为它(尤其是文本)与辅助工具配合得非常好,其中 DirectX 和 OpenGL 都需要实现 MSAA 或 UIA 处理程序才能让我的屏幕阅读器了解文本。

以上是关于正确使用 Win32 设备上下文的主要内容,如果未能解决你的问题,请参考以下文章

win32 C++ 打印 PRINTDLGEX 未声明?

Win32:一个窗口在其整个生命周期中是不是具有相同的 HDC?

如何使用 win32 从多线程上下文初始化线程原语?

Opengl:渲染到 Win32 API 上下文

Win32 Ime

python 调用windowsAPI截图