Winapi 使用OpenGL和Gdi+的GetDC、ReleaseDC、CS#u OWNDC;

Winapi 使用OpenGL和Gdi+的GetDC、ReleaseDC、CS#u OWNDC;,winapi,opengl,gdi+,Winapi,Opengl,Gdi+,阅读关于GetDC/ReleaseDC的文章时,我似乎总是做后者,而窗口上的CS_OWNDC被认为是邪恶的: https://blogs.msdn.microsoft.com/oldnewthing/20060601-06/?p=31003 查看我的代码,我看到我持有一个从GetDC检索到的DC,它已发送到wglCreateContextAttribARB。我假设上下文是在该DC上创建的,因此随后从驱动程序下释放它是不礼貌的。我的假设正确吗?当我销毁其他OpenGL资源时,我正在调用Rele

阅读关于GetDC/ReleaseDC的文章时,我似乎总是做后者,而窗口上的CS_OWNDC被认为是邪恶的:

 https://blogs.msdn.microsoft.com/oldnewthing/20060601-06/?p=31003
查看我的代码,我看到我持有一个从GetDC检索到的DC,它已发送到wglCreateContextAttribARB。我假设上下文是在该DC上创建的,因此随后从驱动程序下释放它是不礼貌的。我的假设正确吗?当我销毁其他OpenGL资源时,我正在调用ReleaseDC

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


那么,这方面是否有明确的最佳实践指南?我努力释放GDI+DC但坚持OpenGL DC的方式似乎有些不一致。

OpenGL和GDI+的行为不同

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

GDI+在MS Windows中的使用与任何常见的
DC
:检索DC,绘制DC,释放DC。在这个场景中,使用CS_OWNDC可能是邪恶的,正如你在文章中指出的那样。
MS GDI+使用图形硬件的方式(即创建上下文或其他)与您无关


编辑由于Chris Becke的评论:

不需要使用CS\u OWNDC

引述:

hdc参数必须引用OpenGL支持的图形表面。 它不必是在运行时传递给wglCreateContext的同一个hdc hglrc已创建,但它必须位于同一设备上,并且具有相同的 像素格式

建议使用CS\U OWNDC。 在Windows9x的旧时代,获取和发布设备上下文既昂贵又缓慢。有一个固定的dc更有效。在窗口注册时使用
CS\u OWNDC
标志是获得固定dc的方法

CS\u OWNDC
用法提供了专用设备上下文(请参阅)。
引用MS文档():

尽管专用设备上下文使用起来很方便,但它是 系统资源方面的内存密集型,需要800或更多 要存储的字节数。建议在以下情况下使用专用设备上下文: 性能方面的考虑超过了存储成本

您必须意识到,您必须避免使用私有设备上下文发布DC:

应用程序可以通过以下方式检索专用设备上下文的句柄: 在创建窗口后的任何时间使用GetDC函数。这个 应用程序只能检索句柄一次。此后,它可以 保持并多次使用手柄。因为这是一个私人设备 上下文不是显示设备上下文缓存的一部分 应用程序永远不需要使用 释放DC功能

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

也可能是使用了
wglGetCurrentDC()
(例如由外部库使用)而没有使用GetDC/ReleaseDC代码的情况。通常不会发生任何问题。但是,如果当前gl上下文为空(就像您在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)

好吧,在我看来,这是一个很好的生活准则。CS_OWNDC在GDI、GDI+的上下文中是不好的。在任何情况下都不坏,这是垃圾。像素格式在窗口上设置,为该窗口检索的所有窗口DC将与gl上下文一起工作。甚至OpenGL也不需要使用CS_OWNDC。@chrisbeck,但在官方的Khronos wiki()中,我们可以看到应该使用CS_OWNDC标志:“当您创建HWND时,您需要确保它的样式设置了CS_OWNDC。”是的,我也读到了。但这是一个质量可疑的维基页面。我在任何官方标准文件中都找不到任何关于这一离奇说法的佐证。它确实与wgl*和SetPixelFormat*函数上的MSDN文档存在隐式冲突,至少对我来说,这些函数的措辞意味着表示窗口的任何HDC都是等效的。@ChrisBecke MSDN说:“GetDC函数根据指定窗口的类样式检索公共、类或私有DC。”因此,当未指定CS_OWNDC标志时,我们将获取公共、类DC。因此,对于此类DC,像素格式只能设置一次。如果我们创建“假”“用于检索扩展和函数以更好地创建OpenGL上下文的窗口,如果我们想创建具有其他上下文的另一个窗口,我们不能选择其他像素格式(例如支持多采样的像素格式)。为此,我们需要一个与给定窗口关联的DC,因此需要CS_OWNDC标志。