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

标签 windows opengl

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

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

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

请在下文中找到我期望它如何根据教程工作的代码:

#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);
}

在下面,我发现了一个让它工作的“黑客”:我基本上将 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);
}

最佳答案

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

关于windows - OpenGL -> wglCreateContext,WndProc 的 WM_CREATE 中的 wglMakeCurrent 使渲染失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16928011/

相关文章:

c++ - OpenGL- C++ 使用鼠标单击将形状移动到单击的位置

opengl - glLoadIdentity() 在 OpenGL 中做什么?

cocoa OpenGL : draw texture and round corners

windows - 启动 apache 服务器时,没有检查系统可用于类型 <type 'instancemethod' > 的对象

c++ - 转换为 HWND 时发出警告

c# - 关闭后保留对话框中的值 - Windows Forms C#

c - GetModuleHandle 实现不起作用

opengl - 如何禁用绘制到颜色缓冲区

c++ - 正常的 Windows 安装是否包含 MFC100.dll?

opengl - 绑定(bind) OpenGL 纹理采样器