Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用并发c+解决问题+;窗户_C++_Windows_Multithreading_Opengl - Fatal编程技术网

C++ 使用并发c+解决问题+;窗户

C++ 使用并发c+解决问题+;窗户,c++,windows,multithreading,opengl,C++,Windows,Multithreading,Opengl,我是第一次学习opengl,我正在尝试制作一个简单的程序。我的程序运行在两个线程中,一个线程在屏幕上呈现程序,而另一个线程更新程序的数据。然而,有时当我试图关闭我的程序时,我会收到一条令人讨厌的错误消息。我不明白为什么,尽管我觉得这是一个并发错误。这是我的密码 Main.cpp #define WIN32_LEAN_AND_MEAN #define WIN32_EXTRA_LEAN #define GLX_GLXEXT_LEGACY #include <windows.h> #in

我是第一次学习opengl,我正在尝试制作一个简单的程序。我的程序运行在两个线程中,一个线程在屏幕上呈现程序,而另一个线程更新程序的数据。然而,有时当我试图关闭我的程序时,我会收到一条令人讨厌的错误消息。我不明白为什么,尽管我觉得这是一个并发错误。这是我的密码

Main.cpp

#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#define GLX_GLXEXT_LEGACY

#include <windows.h>
#include "glwindow.h"
#include "example.h"
#include "util.h"

void updateThread(Example* example);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
{
    const int windowWidth = 1024;
    const int windowHeight = 768;
    const int windowBPP = 16;
    const int windowFullscreen = false;
    GLWindow programWindow(hInstance);
    Example example;
    programWindow.attachExample(&example);

    if (!programWindow.create(windowWidth, windowHeight, windowBPP, windowFullscreen))
    {
        MessageBox(NULL, "Unable to create the OpenGL Window", "An error occurred", MB_ICONERROR | MB_OK);
        programWindow.destroy();
        return 1;
    }

    if (!example.init())
    {
        MessageBox(NULL, "Could not initialize the application", "An error occurred", MB_ICONERROR | MB_OK);
        programWindow.destroy();
        return 1;
    }

    HANDLE thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) updateThread, &example, 0, 0);
    example.setThread(&thread);

    while(programWindow.isRunning())
    {
        programWindow.processEvents();
        example.render();
        programWindow.swapBuffers();
    }

    example.shutdown();
    programWindow.destroy();
    return 0;
}

void updateThread(Example* example)
{
    setFPS(2000);

    while(true)
    {
        example->update();
        sync();
    }
}
glwindow.cpp

#include <ctime>
#include <iostream>
#include <windows.h>
#include <GL/gl.h>
#include "wglext.h"
#include "glwindow.h"
#include "example.h"

typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;

GLWindow::GLWindow(HINSTANCE hInstance):
    m_isRunning(false),
    m_example(NULL),
    m_hinstance(hInstance),
    m_lastTime(0)
{

}

bool GLWindow::create(int width, int height, int bpp, bool fullscreen)
{
    DWORD dwExStyle;
    DWORD dwStyle;
    m_isFullscreen = fullscreen;
    m_windowRect.left = (long)0;
    m_windowRect.right = (long)width;
    m_windowRect.top = (long)0;
    m_windowRect.bottom = (long)height;
    m_windowClass.cbSize = sizeof(WNDCLASSEX);
    m_windowClass.style = CS_HREDRAW | CS_VREDRAW;
    m_windowClass.lpfnWndProc = GLWindow::StaticWndProc;
    m_windowClass.cbClsExtra = 0;
    m_windowClass.cbWndExtra = 0;
    m_windowClass.hInstance = m_hinstance;
    m_windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    m_windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    m_windowClass.hbrBackground = NULL;
    m_windowClass.lpszMenuName = NULL;
    m_windowClass.lpszClassName = "GLClass";
    m_windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

    if(!RegisterClassEx(&m_windowClass))
    {
        return false;
    }

    if(m_isFullscreen)                            
    {
        DEVMODE dmScreenSettings;
        memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
        dmScreenSettings.dmSize = sizeof(dmScreenSettings); 
        dmScreenSettings.dmPelsWidth = width;
        dmScreenSettings.dmPelsHeight = height;
        dmScreenSettings.dmBitsPerPel = bpp;
        dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
        {
            MessageBox(NULL, "Display mode failed", NULL, MB_OK);
            m_isFullscreen = false; 
        }
    }

    if (m_isFullscreen)
    {
        dwExStyle = WS_EX_APPWINDOW;
        dwStyle = WS_POPUP;
        ShowCursor(false);
    }
    else
    {
        dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
        dwStyle = WS_OVERLAPPEDWINDOW;
    }

    AdjustWindowRectEx(&m_windowRect, dwStyle, false, dwExStyle);
    m_hwnd = CreateWindowEx(NULL, "GLClass", "BOGLGP - Chapter 2 - Simple OpenGL Application", dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        0, 0, m_windowRect.right - m_windowRect.left, m_windowRect.bottom - m_windowRect.top, NULL, NULL, m_hinstance, this);

    if (!m_hwnd)
    {
        MessageBox(NULL, "Window Creation Failed", NULL, MB_OK);
        return 1;
    }

    m_hdc = GetDC(m_hwnd);
    ShowWindow(m_hwnd, SW_SHOW);
    UpdateWindow(m_hwnd);
    m_lastTime = GetTickCount() / 1000.0f;
    return true;
}

void GLWindow::destroy() 
{
    if (m_isFullscreen)
    {
        ChangeDisplaySettings(NULL, 0);
        ShowCursor(true);
    }
}

void GLWindow::attachExample(Example* example)
{
    m_example = example;
}

bool GLWindow::isRunning()
{
    return m_isRunning;
}

void GLWindow::processEvents()
{
    MSG msg;

    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

void GLWindow::setupPixelFormat(void)
{
    int pixelFormat;

    PIXELFORMATDESCRIPTOR pfd =
    {   
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_SUPPORT_OPENGL |
        PFD_DRAW_TO_WINDOW |
        PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        16,
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0, 0, 0,
    };

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

LRESULT GLWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_CREATE:
        {
            m_hdc = GetDC(hWnd);
            setupPixelFormat();

            int attribs[] = {
                WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
                WGL_CONTEXT_MINOR_VERSION_ARB, 0,
                0};

            HGLRC tmpContext = wglCreateContext(m_hdc);
            wglMakeCurrent(m_hdc, tmpContext);
            wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");

            if (!wglCreateContextAttribsARB)
            {
                MessageBox(NULL, "Open GL 3.0 Is Not Supported", NULL, MB_OK);
                m_hglrc = tmpContext;
                DestroyWindow(hWnd);
                return 0;
            } 
            else
            {
                m_hglrc = wglCreateContextAttribsARB(m_hdc, 0, attribs);
                wglDeleteContext(tmpContext);
            }

            wglMakeCurrent(m_hdc, m_hglrc);
            m_isRunning = true;
        }

        break;

    case WM_DESTROY:
    case WM_CLOSE:
        wglMakeCurrent(m_hdc, NULL);
        wglDeleteContext(m_hglrc);
        m_isRunning = false;
        PostQuitMessage(0);
        return 0;
        break;

    case WM_SIZE:
        {
            int height = HIWORD(lParam);
            int width = LOWORD(lParam);
            getAttachedExample()->onResize(width, height);
        }

        break;

    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
        {
            DestroyWindow(m_hwnd);
        }
        break;

    default:
        break;
    }

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

LRESULT CALLBACK GLWindow::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    GLWindow* window = NULL;

    if(uMsg == WM_CREATE)
    {
        window = (GLWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
        SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)window);
    }

    else
    {
        window = (GLWindow*)GetWindowLongPtr(hWnd, GWL_USERDATA);

        if(!window) 
        {
            return DefWindowProc(hWnd, uMsg, wParam, lParam);    
        }
    }

    return window->WndProc(hWnd, uMsg, wParam, lParam);
}

float GLWindow::getElapsedSeconds()
{
    float currentTime = float(GetTickCount()) / 1000.0f;
    float seconds = float(currentTime - m_lastTime);
    m_lastTime = currentTime;
    return seconds;
}
#包括
#包括
#包括
#包括
#包括“wglext.h”
#包括“glwindow.h”
#包括“example.h”
typedef HGLRC(apientrypfwnwglcreatecontextattribsarbproc)(HDC、HGLRC、const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB=NULL;
GLWindow::GLWindow(HINSTANCE HINSTANCE):
m_正在运行(错误),
m_示例(空),
m_hinstance(hinstance),
m_上次(0)
{
}
bool GLWindow::create(int-width、int-height、int-bpp、bool-fullscreen)
{
德沃德·德韦克斯风格;
德沃德风格;
m_isFullscreen=全屏;
m_windowRect.left=(长)0;
m_windowRect.right=(长)宽度;
m_windowRect.top=(长)0;
m_windowRect.bottom=(长)高度;
m_windowClass.cbSize=sizeof(WNDCLASSEX);
m_windowClass.style=CS_HREDRAW | CS_VREDRAW;
m_windowClass.lpfnWndProc=GLWindow::StaticWndProc;
m_windowClass.cbClsExtra=0;
m_windowClass.cbWndExtra=0;
m_windowClass.hInstance=m_hInstance;
m_windowClass.hIcon=加载图标(NULL,IDI_应用程序);
m_windowClass.hCursor=LoadCursor(空,IDC_箭头);
m_windowClass.hbrBackground=NULL;
m_windowClass.lpszMenuName=NULL;
m_windowClass.lpszClassName=“GLClass”;
m_windowClass.hIconSm=LoadIcon(NULL,IDI_WINLOGO);
if(!RegisterClass(&m_windowClass))
{
返回false;
}
如果(m_为全屏)
{
DEVMODE DMS筛选设置;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth=宽度;
dmScreenSettings.dmPelsHeight=高度;
dmScreenSettings.dmBitsPerPel=bpp;
dmScreenSettings.dmFields=DM|u BITSPERPEL | DM|u PELSWIDTH | DM|PELSHEIGHT;
if(更改显示设置(&dmScreenSettings,CD\u全屏)!=显示更改成功)
{
消息框(NULL,“显示模式失败”,NULL,MB_OK);
m_isFullscreen=false;
}
}
如果(m_为全屏)
{
dwExStyle=WS_EX_APPWINDOW;
dwStyle=WS_弹出窗口;
ShowCursor(假);
}
其他的
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle=WS_重叠窗口;
}
AdjustWindowRectEx(&m_windowRect,dwStyle,false,dwExStyle);
m|u hwnd=CreateWindowEx(NULL,“GLClass”,“BOGLGP-第2章-简单OpenGL应用程序”,dwStyle | WS|u CLIPCHILDREN | WS|CLIPSIBLINGS,
0,0,m_windowRect.right-m_windowRect.left,m_windowRect.bottom-m_windowRect.top,NULL,NULL,m_hinstance,this);
如果(!m_hwnd)
{
MessageBox(空,“窗口创建失败”,空,MB_OK);
返回1;
}
m_hdc=GetDC(m_hwnd);
显示窗口(m_hwnd,SW_SHOW);
更新域(m_hwnd);
m_lastTime=GetTickCount()/1000.0f;
返回true;
}
void GLWindow::destroy()
{
如果(m_为全屏)
{
ChangeDisplaySettings(空,0);
ShowCursor(true);
}
}
void GLWindow::attachExample(示例*示例)
{
m_示例=示例;
}
bool GLWindow::isRunning()
{
返回m_正在运行;
}
void GLWindow::processEvents()
{
味精;
while(peek消息(&msg,NULL,0,0,PM_-REMOVE))
{
翻译信息(&msg);
发送消息(&msg);
}
}
void GLWindow::setupPixelFormat(void)
{
整数像素格式;
像素描述符pfd=
{   
sizeof(像素格式描述符),
1.
PFD_支持_OPENGL|
PFD_绘图_至_窗口|
PFD_双缓冲器,
PFD_类型_RGBA,
32,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_主飞机,
0,
0, 0, 0,
};
像素格式=选择像素格式(m_hdc和pfd);
SetPixelFormat(m_hdc、pixelFormat和pfd);
}
LRESULT GLWindow::WndProc(HWND HWND、UINT uMsg、WPARAM WPARAM、LPARAM LPARAM)
{
开关(uMsg)
{
案例WM_创建:
{
m_hdc=GetDC(hWnd);
设置像素格式();
int attribs[]={
WGL\U上下文\U主要\U版本\U ARB,3,
WGL_上下文_次要_版本_ARB,0,
0};
HGLRC tmpContext=wglCreateContext(m_hdc);
wglMakeCurrent(m_hdc,tmpContext);
wglCreateContextAttribsARB=(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(“wglCreateContextAttribsARB”);
如果(!wglCreateContextAttribsARB)
{
MessageBox(空,“不支持OpenGL 3.0”,空,MB_OK);
m_hglrc=tmpContext;
窗口(hWnd);
返回0;
} 
其他的
{
m_hglrc=wglCreateContextAttribsARB(m_hdc,0,attribs);
wglDeleteContext(tmpContext);
}
wglMakeCurrent(m_hdc,m_hglrc);
m_isRunning=真;
}
打破
案例WM_销毁:
案例WM_结束:
wglMakeCurrent(m_hdc,空);
wglDeleteContext(m_hglrc);
m_isRunning=假;
PostQuitMessage(0);
返回0;
打破
案例WM_大小:
{
int height=HIWORD(lParam);
int width=LOWORD(LPRAM);
getAttachedExample()->onResize(宽度、高度);
}
打破
案例WM_键控:
if(wParam==VK_转义)
{
破坏窗口(m_hwnd);
}
打破
违约:
打破
}
返回DefWindowProc(hWnd、uMsg、wParam、lParam);
}
爱尔兰
#include <ctime>
#include <iostream>
#include <windows.h>
#include <GL/gl.h>
#include "wglext.h"
#include "glwindow.h"
#include "example.h"

typedef HGLRC (APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC, HGLRC, const int*);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;

GLWindow::GLWindow(HINSTANCE hInstance):
    m_isRunning(false),
    m_example(NULL),
    m_hinstance(hInstance),
    m_lastTime(0)
{

}

bool GLWindow::create(int width, int height, int bpp, bool fullscreen)
{
    DWORD dwExStyle;
    DWORD dwStyle;
    m_isFullscreen = fullscreen;
    m_windowRect.left = (long)0;
    m_windowRect.right = (long)width;
    m_windowRect.top = (long)0;
    m_windowRect.bottom = (long)height;
    m_windowClass.cbSize = sizeof(WNDCLASSEX);
    m_windowClass.style = CS_HREDRAW | CS_VREDRAW;
    m_windowClass.lpfnWndProc = GLWindow::StaticWndProc;
    m_windowClass.cbClsExtra = 0;
    m_windowClass.cbWndExtra = 0;
    m_windowClass.hInstance = m_hinstance;
    m_windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    m_windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    m_windowClass.hbrBackground = NULL;
    m_windowClass.lpszMenuName = NULL;
    m_windowClass.lpszClassName = "GLClass";
    m_windowClass.hIconSm = LoadIcon(NULL, IDI_WINLOGO);

    if(!RegisterClassEx(&m_windowClass))
    {
        return false;
    }

    if(m_isFullscreen)                            
    {
        DEVMODE dmScreenSettings;
        memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
        dmScreenSettings.dmSize = sizeof(dmScreenSettings); 
        dmScreenSettings.dmPelsWidth = width;
        dmScreenSettings.dmPelsHeight = height;
        dmScreenSettings.dmBitsPerPel = bpp;
        dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
        {
            MessageBox(NULL, "Display mode failed", NULL, MB_OK);
            m_isFullscreen = false; 
        }
    }

    if (m_isFullscreen)
    {
        dwExStyle = WS_EX_APPWINDOW;
        dwStyle = WS_POPUP;
        ShowCursor(false);
    }
    else
    {
        dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
        dwStyle = WS_OVERLAPPEDWINDOW;
    }

    AdjustWindowRectEx(&m_windowRect, dwStyle, false, dwExStyle);
    m_hwnd = CreateWindowEx(NULL, "GLClass", "BOGLGP - Chapter 2 - Simple OpenGL Application", dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        0, 0, m_windowRect.right - m_windowRect.left, m_windowRect.bottom - m_windowRect.top, NULL, NULL, m_hinstance, this);

    if (!m_hwnd)
    {
        MessageBox(NULL, "Window Creation Failed", NULL, MB_OK);
        return 1;
    }

    m_hdc = GetDC(m_hwnd);
    ShowWindow(m_hwnd, SW_SHOW);
    UpdateWindow(m_hwnd);
    m_lastTime = GetTickCount() / 1000.0f;
    return true;
}

void GLWindow::destroy() 
{
    if (m_isFullscreen)
    {
        ChangeDisplaySettings(NULL, 0);
        ShowCursor(true);
    }
}

void GLWindow::attachExample(Example* example)
{
    m_example = example;
}

bool GLWindow::isRunning()
{
    return m_isRunning;
}

void GLWindow::processEvents()
{
    MSG msg;

    while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}

void GLWindow::setupPixelFormat(void)
{
    int pixelFormat;

    PIXELFORMATDESCRIPTOR pfd =
    {   
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_SUPPORT_OPENGL |
        PFD_DRAW_TO_WINDOW |
        PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        16,
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0, 0, 0,
    };

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

LRESULT GLWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_CREATE:
        {
            m_hdc = GetDC(hWnd);
            setupPixelFormat();

            int attribs[] = {
                WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
                WGL_CONTEXT_MINOR_VERSION_ARB, 0,
                0};

            HGLRC tmpContext = wglCreateContext(m_hdc);
            wglMakeCurrent(m_hdc, tmpContext);
            wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");

            if (!wglCreateContextAttribsARB)
            {
                MessageBox(NULL, "Open GL 3.0 Is Not Supported", NULL, MB_OK);
                m_hglrc = tmpContext;
                DestroyWindow(hWnd);
                return 0;
            } 
            else
            {
                m_hglrc = wglCreateContextAttribsARB(m_hdc, 0, attribs);
                wglDeleteContext(tmpContext);
            }

            wglMakeCurrent(m_hdc, m_hglrc);
            m_isRunning = true;
        }

        break;

    case WM_DESTROY:
    case WM_CLOSE:
        wglMakeCurrent(m_hdc, NULL);
        wglDeleteContext(m_hglrc);
        m_isRunning = false;
        PostQuitMessage(0);
        return 0;
        break;

    case WM_SIZE:
        {
            int height = HIWORD(lParam);
            int width = LOWORD(lParam);
            getAttachedExample()->onResize(width, height);
        }

        break;

    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
        {
            DestroyWindow(m_hwnd);
        }
        break;

    default:
        break;
    }

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

LRESULT CALLBACK GLWindow::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    GLWindow* window = NULL;

    if(uMsg == WM_CREATE)
    {
        window = (GLWindow*)((LPCREATESTRUCT)lParam)->lpCreateParams;
        SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)window);
    }

    else
    {
        window = (GLWindow*)GetWindowLongPtr(hWnd, GWL_USERDATA);

        if(!window) 
        {
            return DefWindowProc(hWnd, uMsg, wParam, lParam);    
        }
    }

    return window->WndProc(hWnd, uMsg, wParam, lParam);
}

float GLWindow::getElapsedSeconds()
{
    float currentTime = float(GetTickCount()) / 1000.0f;
    float seconds = float(currentTime - m_lastTime);
    m_lastTime = currentTime;
    return seconds;
}
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "example.h"

Example::Example()
{
    m_rotationAngle = 0.0f;
}

bool Example::init()
{
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    return true;
}

void Example::update()
{
    const float SPEED = 15.0f;
    m_rotationAngle += SPEED;

    if (m_rotationAngle > 360.0f)
    {
        m_rotationAngle -= 360.0f;
    }
}

void Example::render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glRotatef(m_rotationAngle, 0, 0, 1);
    glBegin(GL_TRIANGLES);
    glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
    glVertex3f(-1.0f, -0.5f, -4.0f);
    glColor4f(1.0f, 1.0f, 0.0f, 1.0f);
    glVertex3f(1.0f, -0.5f, -4.0f);
    glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
    glVertex3f(0.0f,  0.5f, -4.0f);
    glEnd();
}

void Example::shutdown()
{
    TerminateThread(thread, 0);
}

void Example::onResize(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0f, float(width) / float(height), 1.0f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
while (true) {
  ...
  if (IShouldExit()) break;
}