欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Windows API 搭建OpenGL窗口

程序员文章站 2022-04-08 23:09:01
步骤: 1、创建windows窗口,得到窗口句柄hwnd 2、获取该窗口的设备环境hDC(当然也可以获取其他的设备环境,但我们一般是在创建的窗口上绘制) 3、创建OpenGL绘制环境RC,这个只能从hDC创建 4、将hDC和RC绑定到当前的线程 注:RC表示OpenGL的绘制环境,所有的OpenGL ......

 

步骤:

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

 

运行:

Windows API 搭建OpenGL窗口