winapi - 使用 OpenGL 和 Gdi+ 的 GetDC、ReleaseDC、CS_OWNDC

标签 winapi opengl gdi+

阅读有关 GetDC/ReleaseDC 的内容后,我应该总是选择后者,并且窗口上的 CS_OWNDC 被认为是邪恶的:

 https://blogs.msdn.microsoft.com/oldnewthing/20060601-06/?p=31003

查看我的代码,我发现我持有从 GetDC 检索到的 DC,我已将其发送到 wglCreateContextAttribARB。我假设上下文是在该 DC 上创建的,因此随后从驱动程序下释放它是不礼貌的。我的假设正确吗?目前,当我销毁其他 OpenGL 资源时,我正在调用 ReleaseDC。

此外,在我的库的其他地方,我调用 GetDC 来实例化 GDI+ Graphics 对象,然后在完成绘图后再次释放它。我认为出于性能原因在绘制调用之间保留 DC 和 Graphics 对象会很好,仅在 WM_DISPLAYCHANGE 等上重新创建它。

那么,是否有该领域最佳实践的明确指南?我努力释放 GDI+ DC 但保留 OpenGL DC 的方式似乎有些不一致。

最佳答案

OpenGL 和 GDI+ 的行为不同。

在 OpenGL 中,您需要一个上下文,它附加有一个 DC。这意味着当上下文存在时,DC必须存在。因此,OpenGL 绘制的窗口确实需要 CS_OWNDC 样式。
删除上下文后调用ReleaseDC

GDI+ 在 MS Windows 中的使用就像任何常见的 DC 一样:检索 DC、绘制到它、释放该 DC。在这种情况下,使用 CS_OWNDC 可能是邪恶的,正如 link 中指出的那样。你发布了。
MS GDI+ 使用图形硬件的方式(即创建上下文或其他)与您无关。


编辑由于克里斯·贝克的评论:

不需要使用 CS_OWNDC

引用 https://msdn.microsoft.com/es-es/library/windows/desktop/dd374387(v=vs.85).aspx :

The hdc parameter must refer to a drawing surface supported by OpenGL. It need not be the same hdc that was passed to wglCreateContext when hglrc was created, but it must be on the same device and have the same pixel format.

建议使用 CS_OWNDC。

在 Windows 9x 的过去,获取和释放设备上下文既昂贵又缓慢。拥有固定直流效率要高得多。在窗口注册时使用 CS_OWNDC 标志是获得固定 dc 的方法。

CS_OWNDC 用法提供了私有(private)设备上下文(请参阅 https://msdn.microsoft.com/en-us/library/windows/desktop/ms633574(v=vs.85).aspx#class_styles )。
引用自 MS 文档 (https://msdn.microsoft.com/en-us/library/windows/desktop/dd162872(v=vs.85).aspx):

Although a private device context is convenient to use, it is memory-intensive in terms of system resources, requiring 800 or more bytes to store. Private device contexts are recommended when performance considerations outweigh storage costs.

您必须注意,必须避免使用私有(private)设备上下文的 ReleaseDC:

An application can retrieve a handle to the private device context by using the GetDC function any time after the window is created. The application must retrieve the handle only once. Thereafter, it can keep and use the handle any number of times. Because a private device context is not part of the display device context cache, an application need never release the device context by using the ReleaseDC function.

在常见场景中,您通过检索 DC 绘制到唯一窗口,设置当前上下文、绘制、交换缓冲区并释放 DC 使用 CS_OWNDC 而不是 GetDC&ReleaseDC 是很自然的。

也可能是使用 wglGetCurrentDC() 的情况(例如通过外部库),无论您的 GetDC/ReleaseDC 代码如何。一般情况下不会出现任何问题。但如果当前的 gl-context 为 NULL(正如您在 ReleaseDC 之后所做的那样),那么 wglGetCurrentDC() 将失败。

不带 CS_OWNDC 的代码
在两个具有相同像素格式的窗口中使用将如下所示:

myGLContext = wglCreateContext(...)

//Draw to window A
HDC hdcA = GetDC(hWndA)
wglMakeCurrent(hdcA, myGLContext)
... render...
SwapBuffers(hdcA)
ReleaseDC(hWndA, hdcA)

//Draw to window B
HDC hdcB = GetDC(hWndB)
wglMakeCurrent(hdcB, myGLContext)
... render...
SwapBuffers(hdcB)
ReleaseDC(hWndA, hdcA)

wglMakeCurrent(hdcB, NULL)

关于winapi - 使用 OpenGL 和 Gdi+ 的 GetDC、ReleaseDC、CS_OWNDC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48663815/

相关文章:

c - 在 visual studio 中为 win32 项目引用其他项目

opengl - 我可以有一个没有 Alpha 和深度的默认帧缓冲区吗?

c++ - gluLookAt() 没有按预期工作

c++ - 在 C++ Win32 中创建透明窗口

c++ - Gdiplus::Bitmap 到 BYTE 数组?

security - Win32 : How to use RegisterTypeLib API from standard user

c++ - 繁忙的应用程序导致 Windows 7 上出现错误的 "Not responding"状态 - WM_UPDATE

c++ - 使用不支持超链接的文本编辑器的替代文本将超链接复制到剪贴板

c++ - CUDA/OpenGL 互操作 : Writing to surface object does not erase previous contents

c# - 检索可用的连续内存