我正在编写一个使用 OpenGL 的 win32 应用程序。我希望窗口在调整大小时不断更新。我的渲染代码位于主循环中,并且
DefWindowProc()
在调整大小时进入循环,因此我的主循环代码不会更新窗口。我将渲染代码放在 WM_SIZE
情况下以解决此问题,但每当我使用角调整窗口大小时,都会引发异常(使用边缘调整大小效果很好)。
我的窗口过程
LRESULT CALLBACK windowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_SIZE:
windowWidth = LOWORD(lParam);
windowHeight = HIWORD(lParam);
glViewport(0, 0, windowWidth, windowHeight);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
SwapBuffers(dc);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
如果我注释掉
SwapBuffers(dc);
,错误就不会发生。
这是抛出的异常: Win32OpenGL.exe 中的 0x0000024416BFFEAE 抛出异常:0xC0000005:读取位置 0x000002441DCF5000 时发生访问冲突。
我尝试过的:
WM_PAINT
案例中。PeekMessage()
而不是 GetMessage()
,希望主循环能够继续调整大小。编辑:
针对
SwapBuffers()
的 Microsoft 文档指出:
对于多线程应用程序,在调用 SwapBuffers 之前刷新绘制到同一窗口的任何其他线程中的绘制命令。
windowProc 是否在另一个线程上运行从而导致问题? “刷新绘图命令”是什么意思?
GetDC 返回窗口客户区的设备上下文。当调整窗口大小时,客户区也会发生变化。 (其他事件也可能需要新的 DC,例如更改屏幕分辨率、颜色格式等。)一般来说,这些 DC 仅供临时使用,并不打算无限期保留。
[有用于窗口(CS_OWNDC)和窗口类(CS_CLASSDC)的私有DC。过去,数据中心的总数非常有限,因此不鼓励私人数据中心。使用私人 DC 看起来很方便,但并不是必需的。我从未见过有人在产品中使用过它。]
最好的选择是每次需要绘制窗口时使用 GetDC 和 ReleaseDC。在“实时”调整窗口大小期间会产生大量消息流量。您不会注意到每次重新绘制时获取新 DC 的开销。
事实上,我什至不会理会 WM_SIZE。只需在 WM_PAINT 处理程序中查询窗口(或客户区域)大小并在那里渲染框架(至少用于处理大小调整循环)。