GetDC,ReleaseDC,CS_OWNDC,OpenGL和Gdi +

时间:2018-02-07 12:27:34

标签: 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的方式似乎有些不一致。

1 个答案:

答案 0 :(得分:2)

OpenGL和GDI +表现不同。

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

在MS Windows中使用GDI +就像任何常见的DC一样:检索DC,绘制它,释放该DC。在这个场景中,CS_OWNDC的使用可能是邪恶的,正如你发布的link所指出的那样。
MS GDI +使用图形硬件的方式(即创建上下文或其他)对你来说无关紧要。

编辑由于Chris Becke的评论:

不需要使用CS_OWNDC

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

  

hdc参数必须引用OpenGL支持的绘图表面。   它不一定是传递给wglCreateContext的hdc   hglrc已创建,但它必须位于同一设备上且具有相同的功能   像素格式。

建议使用CS_OWNDC。

在Windows 9x的旧时代,获取和发布设备上下文既昂贵又缓慢。拥有固定直流更有效率。在窗口注册时使用CS_OWNDC标志是获得固定直流的方法。

CS_OWNDC用法提供私有设备上下文(请参阅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):

  

尽管私有设备上下文使用起来很方便,但确实如此   系统资源方面的内存密集型,需要800或更多   要存储的字节数。建议使用私有设备上下文   性能考虑超过存储成本。

您必须意识到必须避免ReleaseDC私有设备上下文:

  

应用程序可以检索私有设备上下文的句柄   在创建窗口后的任何时候使用GetDC功能。该   应用程序必须只检索一次句柄。此后,它可以   保持和使用句柄任意次。因为是私人设备   上下文不是显示设备上下文缓存的一部分   应用程序需要永远不会通过使用   ReleaseDC功能。

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

也可能是使用wglGetCurrentDC()(例如由extern库)而不管您的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)