2016-04-30 53 views
0

我对此代码有问题。没有错误或警告,但当窗口仅调整大小时会显示三角形。使用OpenGL绘制三角形:如何使用两个类来管理

我需要纠正这一点。头文件包含这两个类:Window和WindowGL(基于类的继承)。这段代码有什么问题?

#ifndef OPENGL_H 
#define OPENGL_H 
#define WIN32_LEAN_AND_MEAN 
#include <Windows.h> 

class Window 
{ 
protected: 
    HWND hwnd; 
    long clientWidh; 
    long clientHeight; 
public: 
    Window() :hwnd(NULL){}; 
    LRESULT WndProc(HWND , UINT , WPARAM , LPARAM); 
    bool Initialize(HINSTANCE appHandle, POINT windowPosition, POINT windowSize); 
    WPARAM Run(); 
}; 

class WindowGL : public Window 
{ 
private: 
    HGLRC handleRC; 
    HDC handleDC; 
    bool InitWGL(HWND hwnd); 
    void DestroyWGL(); 
    void SetScene(bool isometricProjection); 
    void Render(); 
public: 
    WindowGL() :Window(), handleRC(NULL), handleDC(NULL){}; 
    LRESULT WndProc(HWND, UINT , WPARAM, LPARAM); 
    bool SetPixels(HDC) const; 
}window; 

#endif 

和.cpp文件:

#include "myHeaderGL.h" 
#include <cstdlib> 
#include <gl/GL.h> 
#include <gl/GLU.h>// not used in this example 

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    return window.WndProc(hWnd, message, wParam, lParam); 
} 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{ 
    POINT windowPosition = { 100, 100 }; 
    POINT windowSize = { 800, 600 }; 
    if (!window.Initialize(hInstance, windowPosition, windowSize)) 
    { 
     MessageBox(NULL, "Initialisation fail.", "OpenGL Application", MB_OK | MB_ICONERROR); 
     return EXIT_FAILURE; 
    } 
    else return window.Run(); 

} 

LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    case WM_PAINT: 
     RECT rect; 
     GetClientRect(hWnd, &rect); 
     clientWidh = rect.right - rect.left; 
     clientHeight = rect.bottom - rect.top; 
     break; 
    default: 
     return(DefWindowProc(hWnd, message, wParam, lParam)); 
    } 
    return 0L; 
} 

LRESULT WindowGL::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    long result = Window::WndProc(hWnd, message, wParam, lParam); 
    switch (message) 
    { 
    case WM_CREATE: 
     if (!InitWGL(hWnd)) 
     { 
      MessageBox(NULL, "Render context fail to load", "My OpenGL", MB_OK | MB_ICONERROR); 
      return EXIT_FAILURE; 
     } 
     SetScene(false); 
     break; 
    case WM_DESTROY: 
     DestroyWGL(); 
     break; 
    case WM_SIZE: 
     SetScene(false); 
     break; 
    case WM_PAINT: 
     Render(); 
     ValidateRect(hWnd, NULL); 
     break; 
    //default: 
     //return (DefWindowProc(hWnd, message, wParam, lParam)); 
    } 
    return result; 
} 

bool Window::Initialize(HINSTANCE appHandle, POINT windowPosition, POINT windowSize) 
{ 
    char windowName[] = "My 1 OpenGL"; 

    WNDCLASSEX wc; 
    wc.cbSize = sizeof(wc); 
    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
    wc.lpfnWndProc = (WNDPROC)::WndProc; 
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0; 
    wc.hInstance = appHandle; 
    wc.hIcon = NULL; 
    wc.hIconSm = NULL; 
    wc.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc.hbrBackground = NULL; 
    wc.lpszMenuName = NULL; 
    wc.lpszClassName = windowName; 

    if (RegisterClassEx(&wc) == 0) return false; 

    hwnd = CreateWindow(
     windowName, 
     windowName, 
     WS_OVERLAPPEDWINDOW, 
     windowPosition.x, windowPosition.y, 
     windowSize.x, windowSize.y, 
     NULL, 
     NULL, 
     appHandle, 
     NULL 
     ); 
    if (!hwnd) return false; 

    ShowWindow(hwnd, SW_SHOW); 
    UpdateWindow(hwnd); 

    return true; 
} 

WPARAM Window::Run() 
{ 
    MSG msg = {0}; 
    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    else 
    { 
     window.Render(); 
    } 
    return msg.wParam; 
} 

bool WindowGL::SetPixels(HDC handleDC) const 
{ 
    PIXELFORMATDESCRIPTOR pfd; 
    ZeroMemory(&pfd, sizeof(pfd)); 
    pfd.nVersion = 1; 
    pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER; 
    pfd.iPixelType = PFD_TYPE_RGBA; 
    pfd.cColorBits = 32; 
    pfd.cDepthBits = 32; 
    pfd.iLayerType = PFD_MAIN_PLANE; 
    int pixFormat = ChoosePixelFormat(handleDC, &pfd); 
    if (pixFormat == 0) return false; 
    if (!SetPixelFormat(handleDC, pixFormat, &pfd)) return false; 

    return true; 
} 

bool WindowGL::InitWGL(HWND hwnd) 
{ 
    handleDC= ::GetDC(hwnd); 
    if (!SetPixels(handleDC)) return false; 

    handleRC = wglCreateContext(handleDC); 
    if (handleRC == NULL) return false; 
    if (!wglMakeCurrent(handleDC, handleRC)) return false; 
    return true; 
} 

void WindowGL::SetScene(bool isometricProjection) 
{ 
    glViewport(0, 0, clientWidh, clientHeight); 

    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 

    float wsp = clientHeight/(float)clientWidh; 
    if (!isometricProjection) 
     glFrustum(-1.0f, 1.0f, wsp*-1.0f, wsp*1.0f, 1.0f, 10.0f); 
    else 
     glOrtho(-1.0f, 1.0f, wsp*-1.0f, wsp*1.0f, 1.0f, 10.0f); 

    glMatrixMode(GL_MODELVIEW); 
    glEnable(GL_DEPTH_TEST); 
} 

void WindowGL::DestroyWGL() 
{ 
    wglMakeCurrent(NULL, NULL); 
    wglDeleteContext(handleRC); 
    ::ReleaseDC(hwnd, handleDC); 
} 

void WindowGL::Render() 
{ 
    const float x0 = 1.0f; 
    const float y0 = 1.0f; 
    const float z0 = 1.0f; 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
    glLoadIdentity(); 
    glTranslatef(0.0f, 0.0f, -3.0f); 
    glColor4f(1.0f, 1.0f, 0.0f, 1.0f); 

    glBegin(GL_TRIANGLES); 
     glVertex3f(-x0, -y0, 0.0f); 
     glVertex3f(x0, -y0, 0.0f); 
     glVertex3f(0.0f, y0, 0.0f); 
    glEnd(); 

    SwapBuffers(handleDC); 
} 

回答

2

要调用Render()只有当发送WM_PAINT,尝试调用它Run()每隔几毫秒。 使用PeekMessage更改GetMessage以防止代码拖延,然后仅在有消息要读取时才使用GetMessage。

EDIT

while(msg.message != WM_QUIT) 
{ 
    if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    Render(); 
    sleep(10); // If you don't want to update the screen too fast 
} 

编辑2

LRESULT Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch (message) 
    { 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    case WM_SIZE || WM_PAINT: // <- the problem was here 
     RECT rect; 
     GetClientRect(hWnd, &rect); 
     clientWidh = rect.right - rect.left; 
     clientHeight = rect.bottom - rect.top; 
     break; 
    default: 
     return(DefWindowProc(hWnd, message, wParam, lParam)); 
    } 
    return 0L; 
} 
+0

Sry基因此。我更新了Run()函数。但仍然是同样的问题。没有改变窗口大小的三角形。 –

+0

我编辑了代码,它应该给你正确的想法。 – FedeWar

+0

是的,我之前编辑过我的代码 - 并且用“更好”的函数PeekMessage()更改了Run(),但仍然没有效果。标题类是这样构建的,我甚至不能在Run()中调用Render()。相反,我可以调用:窗口。渲染(),但它不会改变任何东西。代码来自物理学家编写的书,但作者不提供源代码。你可以尝试在你的机器上编译这些东西吗?谢谢你的帮助。 –