OpenGL - > wglCreateContext,WndProc的WM_CREATE中的wglMakeCurrent使渲染失败

时间:2013-06-04 21:43:21

标签: windows opengl

操作系统:Windows 7,64位 Visual Studio 2010,debug,32位

我正在尝试一个简单的Windows程序来开始使用openGL:所有程序都应该使用glClear清除颜色缓冲区(GL_COLOR_BUFFER_BIT)。

在我在网络上找到的教程中,我发现人们在创建窗口期间创建和设置openGL上下文(因此在处理WM_CREATE消息期间)。不知何故,我发现这对我的代码不起作用,我似乎无法弄明白。所以如果有人能指出我正确的方向。

请在下面的代码中找到我希望它应该如何工作的代码:

#include <windows.h>
#include <GL\glew.h>
#include <GL\wglew.h>

#include "Application.h"

HWND ghMainWnd = 0;

bool InitWindowsApp(HINSTANCE instanceHandle, int show);

int Run();

LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;

void SetupPixelFormat()
{
    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cAlphaBits = 8;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int pixelFormat = ChoosePixelFormat(hDC, &pfd);
    if(pixelFormat == 0)
    {
        MessageBox(ghMainWnd, L"ChoosePixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
        exit(1);
    }

    if(!SetPixelFormat(hDC, pixelFormat, &pfd))
    {
        MessageBox(ghMainWnd, L"SetPixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
        exit(1);
    }
}

int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
{
    if(!InitWindowsApp(hInstance, nShowCmd))
        return 0;

    return Run();
}

bool InitWindowsApp(HINSTANCE instanceHandle, int show)
{
    WNDCLASS wc;
    wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = instanceHandle;
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = 0;
    wc.lpszClassName = L"BasicWndClass";

    if(!RegisterClass(&wc))
    {
        MessageBox(0, L"RegisterClass failed", 0, 0);
        return false;
    }

    ghMainWnd = CreateWindow(
        L"BasicWndClass",
        L"BasicWindowsApp",
        WS_OVERLAPPEDWINDOW, 
        0,
        0,
        600,
        600,
        0,
        0,
        instanceHandle,
        0);

    if(ghMainWnd == 0)
    {   
        MessageBox(0, L"CreateWindow failed", 0, 0);
        return false;
    }

    ShowWindow(ghMainWnd, show);
    UpdateWindow(ghMainWnd);

    return true;

}

int Run()
{
    MSG msg = {0};

    Application *pApp = new Application();
    pApp->Init();

    while(msg.message != WM_QUIT)
    {
        if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            //Do Other stuff
            pApp->Draw();
            SwapBuffers(hDC);
        }
    }

    if(pApp)
    {
        delete pApp;
        pApp = nullptr;
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    switch(msg)
    {
    case WM_CREATE:

        hDC = GetDC(ghMainWnd);

        SetupPixelFormat();

        hGLRC = wglCreateContext(hDC);
        if(!hGLRC)
        {
            MessageBox(ghMainWnd, L"wglCreateContext() failed", L"Error", MB_ICONERROR | MB_OK);
            exit(1);
        }

        if(!wglMakeCurrent(hDC, hGLRC))
        {
            MessageBox(ghMainWnd, L"wglMakeCurrent() failed", L"Error", MB_ICONERROR | MB_OK);
            exit(1);
        }

        glViewport(0, 0, 600, 600);
        glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

        return 0;

    case WM_LBUTTONDOWN:

        return 0;

    case WM_KEYDOWN:
        if(wParam == VK_ESCAPE)
            DestroyWindow(ghMainWnd);

        return 0;

    case WM_DESTROY:
        if(hGLRC)
        {
            wglMakeCurrent(nullptr, nullptr);
            wglDeleteContext(hGLRC);
        }

        ReleaseDC(ghMainWnd, hDC);

        PostQuitMessage(0);

        return 0;
    }

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

下面,我发现了一个“hack”使其工作:我基本上将opengl上下文创建移动到InitWindowsApp()函数中...但为什么上面的代码不起作用?

#include <windows.h>
#include <GL\glew.h>
#include <GL\wglew.h>

#include "Application.h"

HWND ghMainWnd = 0;

bool InitWindowsApp(HINSTANCE instanceHandle, int show);

int Run();

LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

HDC hDC;
HGLRC hGLRC;
HPALETTE hPalette;

void SetupPixelFormat()
{
    PIXELFORMATDESCRIPTOR pfd = {};
    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 24;
    pfd.cAlphaBits = 8;
    pfd.cDepthBits = 32;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int pixelFormat = ChoosePixelFormat(hDC, &pfd);
    if(pixelFormat == 0)
    {
        MessageBox(ghMainWnd, L"ChoosePixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
        exit(1);
    }

    if(!SetPixelFormat(hDC, pixelFormat, &pfd))
    {
        MessageBox(ghMainWnd, L"SetPixelFormat() failed", L"Error", MB_ICONERROR | MB_OK);
        exit(1);
    }
}

int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd)
{
    if(!InitWindowsApp(hInstance, nShowCmd))
        return 0;

    return Run();
}

bool InitWindowsApp(HINSTANCE instanceHandle, int show)
{
    WNDCLASS wc;
    wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = instanceHandle;
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = 0;
    wc.lpszClassName = L"BasicWndClass";

    if(!RegisterClass(&wc))
    {
        MessageBox(0, L"RegisterClass failed", 0, 0);
        return false;
    }

    ghMainWnd = CreateWindow(
        L"BasicWndClass",
        L"BasicWindowsApp",
        WS_OVERLAPPEDWINDOW, 
        0,
        0,
        600,
        600,
        0,
        0,
        instanceHandle,
        0);

    if(ghMainWnd == 0)
    {   
        MessageBox(0, L"CreateWindow failed", 0, 0);
        return false;
    }

    ShowWindow(ghMainWnd, show);
    UpdateWindow(ghMainWnd);

    hDC = GetDC(ghMainWnd);

    SetupPixelFormat();

    hGLRC = wglCreateContext(hDC);
    if(!hGLRC)
    {
        MessageBox(ghMainWnd, L"wglCreateContext() failed", L"Error", MB_ICONERROR | MB_OK);
        exit(1);
    }

    if(!wglMakeCurrent(hDC, hGLRC))
    {
        MessageBox(ghMainWnd, L"wglMakeCurrent() failed", L"Error", MB_ICONERROR | MB_OK);
        exit(1);
    }

    glViewport(0, 0, 600, 600);
    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);

    return true;

}

int Run()
{
    MSG msg = {0};

    Application *pApp = new Application();
    pApp->Init();

    while(msg.message != WM_QUIT)
    {
        if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            //Do Other stuff
            pApp->Draw();
            SwapBuffers(hDC);
        }
    }

    if(pApp)
    {
        delete pApp;
        pApp = nullptr;
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    switch(msg)
    {
    case WM_CREATE:

        return 0;

    case WM_LBUTTONDOWN:

        return 0;

    case WM_KEYDOWN:
        if(wParam == VK_ESCAPE)
            DestroyWindow(ghMainWnd);

        return 0;

    case WM_DESTROY:
        if(hGLRC)
        {
            wglMakeCurrent(nullptr, nullptr);
            wglDeleteContext(hGLRC);
        }

        ReleaseDC(ghMainWnd, hDC);

        PostQuitMessage(0);

        return 0;
    }

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

1 个答案:

答案 0 :(得分:4)

WM_CREATE到达时,您的ghMainWnd仍为NULL(在CreateWindow调用返回之前发送消息)。而是在GetDC调用中使用消息的hWnd参数。