绘制的openGL消失在窗口调整大小

时间:2017-04-28 01:27:02

标签: c++ c opengl

我试图用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);
}

3 个答案:

答案 0 :(得分:1)

CS_OWNDChbrBackground添加到NULL并覆盖WM_ERASEBKGND

答案 1 :(得分:0)

  

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

重绘WM_SIZE并禁用背景清除(不禁用背景清除的东西会闪烁)。您可以通过在WNDCLASS中设置NULL背景画笔并返回非零以响应WM_ERASEBKGD消息来完成此操作。

答案 2 :(得分:0)

在整个应用程序生命周期中,一劳永逸地保持窗口DC。每当您使用CS_OWNDCGetDC获得DC时,如果您没有在课堂风格中使用BeginPaint或其他DC保留标记,那么您将获得字面上的新DC,即不再与GL上下文相关联。

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

// 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,只能调用一次。