无法使我的第一个Windows OpenGL窗口抬起并运行

Unable to get my first Windows opengl window up and running

本文关键字:窗口 运行 OpenGL Windows 我的 第一个      更新时间:2023-10-16

我正在尝试启动将在Windows 10和US OpenGL上运行的应用程序。我可以在屏幕上找到一个窗口,但是初始化OpenGL后,我无法在窗口中显示出颜色。我试图不使用诸如GLFW之类的第三方库。

我当前的代码如下:

#include <Windows.h>
#include <gl/gl.h>
#include <cassert>
#define local_persist static
#define local_func static
#define global_variable static
namespace Win64
{
    local_func void
    ProcessPendingMessages()
    {
        MSG Message;
        while(GetMessageA(&Message, 0, 0, 0))
        {
            switch(Message.message)
            {
                case WM_QUIT:
                {
                } break;
                case WM_SYSKEYDOWN:
                case WM_SYSKEYUP:
                case WM_KEYDOWN:
                case WM_KEYUP:
                {
                    uint32 VKCode = (uint32)Message.wParam;
                    if(VKCode == 'W')
                    {
                    }
                    else if(VKCode == 'A')
                    {
                    }
                    else if(VKCode == 'S')
                    {
                    }
                    else if(VKCode == 'D')
                    {
                    }
                    else if(VKCode == 'Q')
                    {
                    }
                    else if(VKCode == 'E')
                    {
                    }
                    else if(VKCode == VK_UP)
                    {
                    }
                    else if(VKCode == VK_LEFT)
                    {
                    }
                    else if(VKCode == VK_DOWN)
                    {
                    }
                    else if(VKCode == VK_RIGHT)
                    {
                    }
                    else if(VKCode == VK_ESCAPE)
                    {
                    }
                    else if(VKCode == VK_SPACE)
                    {
                    }
                }
                default:
                {
                    TranslateMessage(&Message);
                    DispatchMessageA(&Message);
                } break;
            }
        }
    };
    LRESULT CALLBACK
    ProgramWindowCallback(HWND WindowHandle, UINT Message, WPARAM wParam, LPARAM lParam)
    {
        LRESULT Result{0};
        switch(Message)
        {
            case WM_SIZE:
            {
                OutputDebugStringA("WM_SIZEn");
            }break;
            case WM_DESTROY:
            {
                OutputDebugStringA("WM_DESTROYn");
            }break;
            case WM_CLOSE:
            {
                OutputDebugStringA("WM_CLOSEn");
            }break;
            case WM_ACTIVATEAPP:
            {
                OutputDebugStringA("WM_ACTIVATEAPPn");
            }break;
            case WM_PAINT:
            {
                PAINTSTRUCT Paint;
                RECT ClientRect;
                GetClientRect(WindowHandle, &ClientRect);
                HDC DeviceContext = BeginPaint(WindowHandle, &Paint);
                LONG Width = ClientRect.right - ClientRect.left;
                LONG Height = ClientRect.bottom - ClientRect.top;
                glViewport(0, 0, Width, Height);
                glClearColor(1.0f, 0.0f, 1.0f, 0.0f);
                glClear(GL_COLOR_BUFFER_BIT);
                SwapBuffers(DeviceContext);
                EndPaint(WindowHandle, &Paint);
            }break;
            default:
            {
                Result = DefWindowProc(WindowHandle, Message, wParam, lParam);
            }break;
        }
        return Result;
    };
}
int CALLBACK WinMain(HINSTANCE CurrentProgramInstance, HINSTANCE PrevInstance, LPSTR CommandLine, int ShowCode)
{
    WNDCLASS WindowProperties{};
    //TODO: Check if OWNDC/HREDRAW/VEDRAW matter
    WindowProperties.style = CS_OWNDC|CS_HREDRAW|CS_VREDRAW;
    WindowProperties.lpfnWndProc = Win64::ProgramWindowCallback;
    WindowProperties.hInstance = CurrentProgramInstance;
    WindowProperties.lpszClassName = "MemoWindowClass";
    if(RegisterClass(&WindowProperties))
    {
        HWND Window = CreateWindowEx(0, WindowProperties.lpszClassName, "Memo", WS_OVERLAPPEDWINDOW|WS_VISIBLE, 
                                     CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, CurrentProgramInstance, 0);
        if(Window)
        {
            HDC WindowDeviceContext = GetDC(Window);
            { //Init OpenGL
                HGLRC OpenGLRenderingContext = wglCreateContext(WindowDeviceContext);
                PIXELFORMATDESCRIPTOR DesiredPixelFormat{};
                DesiredPixelFormat.nSize = sizeof(DesiredPixelFormat);
                DesiredPixelFormat.nVersion = 1;
                DesiredPixelFormat.iPixelType = PFD_TYPE_RGBA;
                DesiredPixelFormat.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER;
                DesiredPixelFormat.cColorBits = 32;
                DesiredPixelFormat.cAlphaBits = 8;
                DesiredPixelFormat.iLayerType = PFD_MAIN_PLANE;
                int SuggestedPixelFormatIndex = ChoosePixelFormat(WindowDeviceContext, &DesiredPixelFormat);
                PIXELFORMATDESCRIPTOR SuggestedPixelFormat{};
                DescribePixelFormat(WindowDeviceContext, SuggestedPixelFormatIndex, sizeof(SuggestedPixelFormat), &SuggestedPixelFormat);
                if (SetPixelFormat(WindowDeviceContext, SuggestedPixelFormatIndex, &SuggestedPixelFormat))
                {
                    if (wglMakeCurrent(WindowDeviceContext, OpenGLRenderingContext))
                    {
                        //Success!
                    }
                    else
                    {
                        //Log error
                        assert(1 == 0);
                    }
                }
                else
                {
                    //Log error
                    assert(1 == 0);
                }
            }
            Win64::ProcessPendingMessages();
        }
    }
    return 0;
}

我希望glclear((能清除我在glclearcolor((中设置的颜色。但是这没有发生。我做错了什么?

wglMakeCurrent之前移动呼叫wglCreateContext()的行,然后在设置Pixel格式之后(SetPixelFormat()调用(。

if (SetPixelFormat(WindowDeviceContext, SuggestedPixelFormatIndex, &SuggestedPixelFormat))
{
    HGLRC OpenGLRenderingContext = wglCreateContext(WindowDeviceContext);
    if (wglMakeCurrent(WindowDeviceContext, OpenGLRenderingContext))
    //...

创建渲染上下文并使之最新。

OpenGL Win32教程样本代码

我不知道这是否是问题,但是许多OpenGL样本中有一个可怕的反模式,可以使用CS_OWNDC创建窗口类,然后假设其安全地调用WGLMakeCurrent一次在程序启动时,再也不会。

从窗口类中省略CS_OWNDC样式是远,更安全,只需将所有输入点与wglmakecurrent用wglmakecurrent包装到您的OpenGL调用中,然后清理。

模式是,您想使用openGL做一些事情,以便您拨打getdc/beginpaint以获取窗口DC,然后呼叫WGLMakeCurrent通过DC和GL RC句柄,进行OpenGL呼叫,然后在您之前致电reparesc/endPaint,您再次致电wglmakecurrent再次通过null,null。

遵循此基本建议,您可以在单个线程上安全地创建多个打开的GL窗口实例,并且您不必担心某些第三方代码可能会创建某些第三方代码,并暂时使其自身的GL上下文。