Windows API 搭建OpenGL窗口

旧城冷巷雨未停 提交于 2020-04-28 23:22:26

 

步骤:

1、创建windows窗口,得到窗口句柄hwnd

2、获取该窗口的设备环境hDC(当然也可以获取其他的设备环境,但我们一般是在创建的窗口上绘制)

3、创建OpenGL绘制环境RC,这个只能从hDC创建

4、将hDC和RC绑定到当前的线程

 

注:RC表示OpenGL的绘制环境,所有的OpenGL命令都会在RC这个绘制环境中作用,所以必须在RC绑定到当前线程之后才能调用OpenGL命令,否则运行出错,内存访问错误。

  一般的笔刷绘制,在hDC下即可。

 

封装的窗口类如下:

  GLWindow.h

#pragma once
#include <windows.h>
#include <GL/glew.h>
#include <iostream>
class GLContext
{
public:
    GLContext();
    ~GLContext();
    void Setup(HWND,HDC);
    void SetupPixelFormat(HDC);
private:
    HWND hWnd;
    HDC hDC;
    HGLRC hRC;
    int format;
};

GLContext::GLContext()
{
    this->hWnd = 0;
    this->hDC = 0;
    this->hRC = 0;
    this->format = 0;
}
GLContext::~GLContext()
{
}

void GLContext::SetupPixelFormat(HDC hDC) {
    int pixelFormat;

    PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),  // size
        1,                          // version
        PFD_SUPPORT_OPENGL |        // OpenGL window
        PFD_DRAW_TO_WINDOW |        // render to window
        PFD_DOUBLEBUFFER,           // support double-buffering
        PFD_TYPE_RGBA,              // color type
        32,                         // prefered color depth
        0, 0, 0, 0, 0, 0,           // color bits (ignored)
        0,                          // no alpha buffer
        0,                          // alpha bits (ignored)
        0,                          // no accumulation buffer
        0, 0, 0, 0,                 // accum bits (ignored)
        16,                         // depth buffer
        0,                          // no stencil buffer
        0,                          // no auxiliary buffers
        PFD_MAIN_PLANE,             // main layer
        0,                          // reserved
        0, 0, 0,                    // no layer, visible, damage masks
    };

    pixelFormat = ChoosePixelFormat(hDC, &pfd);
    SetPixelFormat(hDC, pixelFormat, &pfd);
}

void GLContext::Setup(HWND hwnd, HDC hdc) {
    this->hWnd = hwnd;
    this->hDC = hdc;
    SetupPixelFormat(hDC);
    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);

    //initialize glew
    glewExperimental = GL_TRUE;
    glewInit();
    if (AllocConsole())
    {
        freopen("CONOUT$", "w+t", stdout);
        freopen("CONOUT$", "w+t", stderr);
        const GLubyte* Devise = glGetString(GL_RENDERER);    //返回一个渲染器标识符,通常是个硬件平台  
        const GLubyte* str = glGetString(GL_VERSION);
        printf("OpenGL实现的版本号:%s\n", str);
        printf("硬件平台:%s\n", Devise);
    }
}




LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

class GLWindow
{
public:
    GLWindow();
    ~GLWindow();
    void Setup(HINSTANCE, HINSTANCE, LPSTR, int);
    //LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    void RegisterDisplayFunc(void (*display)()) {
        this->Display = display;
    }
    void Run();

private:
    void(*Display)();

private:
    bool exiting = false;
    long windowWidth = 800;
    long windowHeight = 600;
    long windowBits = 64;
    bool fullscreen = false;

    WNDCLASSEX windowClass;     // window class
    HWND       hwnd;            // window handle
    HDC           hDC;
    MSG        msg;             // message
    DWORD      dwExStyle;       // Window Extended Style
    DWORD      dwStyle;         // Window Style
    RECT       windowRect;

    GLContext glContext;
};
GLWindow::GLWindow() {}
GLWindow::~GLWindow() {}

void GLWindow::Setup(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    windowRect.left = (long)0;                        // Set Left Value To 0
    windowRect.right = (long)windowWidth; // Set Right Value To Requested Width
    windowRect.top = (long)0;                         // Set Top Value To 0
    windowRect.bottom = (long)windowHeight;   // Set Bottom Value To Requested Height
    
                                              // fill out the window class structure
    windowClass.cbSize = sizeof(WNDCLASSEX);
    windowClass.style = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc = MainWindowProc;    //当窗体触发任何一个事件时,便会调用该函数  
    windowClass.cbClsExtra = 0;
    windowClass.cbWndExtra = 0;
    windowClass.hInstance = hInstance;
    windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);  // default icon
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);      // default arrow
    windowClass.hbrBackground = NULL;                             // don't need background
    windowClass.lpszMenuName = NULL;                             // no menu
    windowClass.lpszClassName = L"Windows API";
    windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);      // windows logo small icon

                                                            // register the windows class
    if (!RegisterClassEx(&windowClass)) {
        puts("Register Class Failed");
    }
    dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window Extended Style
    dwStyle = WS_OVERLAPPEDWINDOW;                    // Windows Style
    AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);     // Adjust Window To True Requested Size

                                                                    // class registered, so now create our window
    hwnd = CreateWindowEx(NULL,                                 // extended style
        L"Windows API",                          // class name
        L"OpenGL",      // app name
        dwStyle | WS_CLIPCHILDREN |
        WS_CLIPSIBLINGS,
        0, 0,                               // x,y coordinate
        windowRect.right - windowRect.left,
        windowRect.bottom - windowRect.top, // width, height
        NULL,                               // handle to parent
        NULL,                               // handle to menu
        hInstance,                          // application instance
        NULL);                              // no extra params

    ShowWindow(hwnd, SW_SHOW);          // display the window
    UpdateWindow(hwnd);                 // update the window
    hDC = GetDC(hwnd);
    glContext.Setup(hwnd,hDC);
}

LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    int height, width;

    // dispatch messages
    switch (uMsg)
    {
    case WM_CREATE:         // window creation
        break;

    case WM_DESTROY:            // window destroy
    case WM_QUIT:
        CloseWindow(hWnd);
        break;
    case WM_CLOSE:                  // windows is closing

                                    // deselect rendering context and delete it
                                    //wglMakeCurrent(hDC, NULL);
                                    //wglDeleteContext(hRC);
                                    // send WM_QUIT to message queue
        PostQuitMessage(0);
        break;

    case WM_SIZE:
        height = HIWORD(lParam);        // retrieve width and height
        width = LOWORD(lParam);
        break;

    case WM_ACTIVATEAPP:        // activate app
        break;

    case WM_PAINT:              // paint
        PAINTSTRUCT ps;
        BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;

    case WM_LBUTTONDOWN:        // left mouse button
        break;

    case WM_RBUTTONDOWN:        // right mouse button
        break;

    case WM_MOUSEMOVE:          // mouse movement
        break;

    case WM_LBUTTONUP:          // left button release
        break;

    case WM_RBUTTONUP:          // right button release
        break;

    case WM_KEYUP:
        break;

    case WM_KEYDOWN:
        int fwKeys;
        LPARAM keyData;
        fwKeys = (int)wParam;    // virtual-key code 
        keyData = lParam;          // key data 

        switch (fwKeys)
        {
            case VK_ESCAPE:
                PostQuitMessage(0);
                break;
            default:
                break;
        }
        break;

    default:
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

void GLWindow::Run() {
    while (true)
    {
        (*Display)();
        SwapBuffers(hDC);
        while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
        {
            if (!GetMessage(&msg, NULL, 0, 0))
            {
                exiting = true;
                break;
            }
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

 

主函数调用代码示例:

#include <Windows.h>
#include <cameras/phc.h>
#include "shader.h"
#include "Cube.h"
#include "GLWindow.h"
redips::PhC phc;
GLWindow window;

Shader* shader;
Cube* cube;

void Display() {
    cube->Draw(*shader, phc);
}

void Initialize(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    phc.lookAt(redips::float3(0, 0, 200), redips::float3(0, 0, 0), redips::float3(0, 1, 0));
    window.Setup(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
    window.RegisterDisplayFunc(Display);

    shader = new Shader("./joint.vert", "./joint.frag");
    cube = new Cube();
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{    
    Initialize(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
    
    window.Run();
    return 1;
}

 

运行:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!