Win32:SwapBuffers() 在窗口调整大小时抛出异常

问题描述 投票:0回答:1

我正在编写一个使用 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 是否在另一个线程上运行从而导致问题? “刷新绘图命令”是什么意思?

c++ winapi opengl
1个回答
0
投票

GetDC 返回窗口客户区的设备上下文。当调整窗口大小时,客户区也会发生变化。 (其他事件也可能需要新的 DC,例如更改屏幕分辨率、颜色格式等。)一般来说,这些 DC 仅供临时使用,并不打算无限期保留。

[有用于窗口(CS_OWNDC)和窗口类(CS_CLASSDC)的私有DC。过去,数据中心的总数非常有限,因此不鼓励私人数据中心。使用私人 DC 看起来很方便,但并不是必需的。我从未见过有人在产品中使用过它。]

最好的选择是每次需要绘制窗口时使用 GetDC 和 ReleaseDC。在“实时”调整窗口大小期间会产生大量消息流量。您不会注意到每次重新绘制时获取新 DC 的开销。

事实上,我什至不会理会 WM_SIZE。只需在 WM_PAINT 处理程序中查询窗口(或客户区域)大小并在那里渲染框架(至少用于处理大小调整循环)。

© www.soinside.com 2019 - 2024. All rights reserved.