【问题标题】:Drawn openGL disappearing on window resize绘制的openGL在窗口调整大小时消失
【发布时间】:2017-09-25 23:56:45
【问题描述】:

我正在尝试创建自己的完全使用 openGL 绘制的窗口。

到目前为止,一切都在绘制。

我遇到的问题是,当我调整窗口大小时,一切都消失了。

如果我不使用DwmEnableBlurBehindWindow,窗口会被绘制成黑色,调整大小时(我不想要这个)

#include <windows.h>
#include <windowsx.h>
#include <GL/gl.h>
#include <GL/glu.h>

#include <dwmapi.h>

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glu32.lib")

#pragma comment (lib, "dwmapi.lib")


const TCHAR szAppName[] = L"TransparentGL";
const TCHAR wcWndName[] = L"TransparentGL";

HDC hDC;
HGLRC m_hrc;
int w = 240;
int h = 240;

BOOL initSC()
{
    glEnable(GL_ALPHA_TEST);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_COLOR_MATERIAL);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glClearColor(0, 0, 0, 0);

    return 0;
}

void resizeSC(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

BOOL renderSC()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();

    POINT start = { 2,2 };
    POINT finish = { w - 2, h - 2 };

    glColor3ub(0, 255, 0);
    glBegin(GL_QUADS);
    glVertex3i(-1, -1, -1);
    glVertex3i(1, -1, -1);
    glVertex3i(1, 1, -1);
    glVertex3i(-1, 1, -1);
    glEnd();

    gluOrtho2D(0, w, 0, h);
    glColor3ub(255, 255, 255);
    glBegin(GL_QUADS);
    glVertex2f(start.x, start.y);
    glVertex2f(finish.x, start.y);
    glVertex2f(finish.x, finish.y);
    glVertex2f(start.x, finish.y);
    glEnd();

    glPopMatrix();
    glFlush();

    return 0;
}

BOOL CreateHGLRC(HWND hWnd)
{
    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,                                // Version Number
        PFD_DRAW_TO_WINDOW |            // Format Must Support Window
        PFD_SUPPORT_OPENGL |            // Format Must Support OpenGL
        PFD_SUPPORT_COMPOSITION |         // Format Must Support Composition
        PFD_DOUBLEBUFFER,                 // Must Support Double Buffering
        PFD_TYPE_RGBA,                    // Request An RGBA Format
        32,                               // Select Our Color Depth
        0, 0, 0, 0, 0, 0,                 // Color Bits Ignored
        8,                                // An Alpha Buffer
        0,                                // Shift Bit Ignored
        0,                                // No Accumulation Buffer
        0, 0, 0, 0,                       // Accumulation Bits Ignored
        24,                               // 16Bit Z-Buffer (Depth Buffer)
        8,                                // Some Stencil Buffer
        0,                                // No Auxiliary Buffer
        PFD_MAIN_PLANE,                   // Main Drawing Layer
        0,                                // Reserved
        0, 0, 0                           // Layer Masks Ignored
    };

    HDC hdc = GetDC(hWnd);
    int PixelFormat = ChoosePixelFormat(hdc, &pfd);
    if (PixelFormat == 0) {
        return FALSE;
    }

    BOOL bResult = SetPixelFormat(hdc, PixelFormat, &pfd);
    if (bResult == FALSE) {
        return FALSE;
    }

    m_hrc = wglCreateContext(hdc);
    if (!m_hrc) {
        return FALSE;
    }

    ReleaseDC(hWnd, hdc);

    return TRUE;
}

LRESULT CALLBACK WindowFunc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
    {
        DWM_BLURBEHIND bb = { 0 };
        HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
        bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
        bb.hRgnBlur = hRgn;
        bb.fEnable = TRUE;
        DwmEnableBlurBehindWindow(hWnd, &bb);

        CreateHGLRC(hWnd);
        break;
    }

    case WM_DESTROY:
        if (m_hrc) {
            wglMakeCurrent(NULL, NULL);
            wglDeleteContext(m_hrc);
        }
        PostQuitMessage(0);
        break;

    case WM_SIZE:
    {
        w = LOWORD(lParam);
        h = HIWORD(lParam);

        HDC hdc = GetDC(hWnd);
        wglMakeCurrent(hdc, m_hrc);
        resizeSC(w, h);
        ReleaseDC(hWnd, hdc);
        break;
    }

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        {
            wglMakeCurrent(hdc, m_hrc);
            renderSC();
            SwapBuffers(hdc);
        }
        EndPaint(hWnd, &ps);

        break;
    }

    case WM_NCCALCSIZE:
        return 0;

    case WM_NCHITTEST:
    {
        LRESULT lResult = DefWindowProc(hWnd, msg, wParam, lParam);
        if (lResult == HTCLIENT)
        {
            POINT pt = { LOWORD(lParam), HIWORD(lParam) };
            ScreenToClient(hWnd, &pt);

            if (GetActiveWindow() == hWnd)
            {
                if (pt.y < 31)
                    return HTCAPTION;
            }

            if (pt.y > (h - 10))
            {
                if (pt.x > (w - 10))
                {
                    return HTBOTTOMRIGHT;
                }
            }
        }

        return lResult;
    }
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, LPSTR str, int nWinMode)
{
    WNDCLASSEX wc;
    memset(&wc, 0, sizeof(wc));
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WindowFunc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hThisInst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(0x00000000);
    wc.lpszClassName = szAppName;

    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, L"RegisterClassEx - failed", L"Error", MB_OK | MB_ICONERROR);
        return FALSE;
    }

    HWND hWnd = CreateWindowEx(WS_EX_APPWINDOW, szAppName, wcWndName,
        WS_VISIBLE, 200, 150, w, h,
        NULL, NULL, hThisInst, NULL);

    if (!hWnd) {
        MessageBox(NULL, L"CreateWindowEx - failed", L"Error", MB_OK | MB_ICONERROR);
        return FALSE;
    }

    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (FALSE);
}

【问题讨论】:

  • 如果当你调整窗口大小时一切都消失了,那么你应该有一个函数,每次调整窗口大小时再次运行绘图?
  • @FelipeLopez 我将SwapBuffers(hdc); 添加到WM_SIZE 它总是被绘制但现在我像疯了一样闪烁
  • 闪烁可能是因为它正在尝试绘制,即使窗口没有调整大小?它应该只利用调整大小
  • C++ 和 C 是非常不同的语言。对其中一个使用标签,但不要同时使用。

标签: c++ c opengl


【解决方案1】:

在整个应用程序生命周期中一劳永逸地保留窗口DC。如果您每次使用GetDCBeginPaint 获得DC 时都没有CS_OWNDC 或其他类风格的DC 保留标志,那么您将获得不再与GL 上下文关联的新DC。

所以,这就是你应该拥有的:

// app init
HWND mywnd = CreateMyWindow();
HDC mywnddc = GetDC(mywnd);
// create context for mywnddc and make it current on mywnddc!

// paint
BeginPaint(wnd, &ps);
EndPaint(&ps);
SwapBuffers(mywnddc); // not the DC you get by BeginPaint!

// app finish
ReleaseDC(mywnd, mywnddc);

如果您不在多个窗口上使用渲染,那么每次要绘制时都调用wglMakeCurrent 是没有意义的,只需调用一次。

【讨论】:

    【解决方案2】:

    我遇到的问题是,当我调整窗口大小时,一切都消失了。

    在 WM_SIZE 上重绘并禁用背景清除(不禁用背景清除会闪烁)。为此,您可以在 WNDCLASS 中设置 NULL 背景画笔并返回非零值以响应 WM_ERASEBKGD 消息。

    【讨论】:

    • 他已经有 CS_HREDRAW |窗口类样式中的 CS_WREDRAW 会在调整大小时完全重绘
    【解决方案3】:

    CS_OWNDChbrBackground 添加到NULL 并覆盖WM_ERASEBKGND

    【讨论】:

      猜你喜欢
      • 2011-09-29
      • 1970-01-01
      • 2017-09-03
      • 1970-01-01
      • 2015-05-23
      • 2011-03-17
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      相关资源
      最近更新 更多