2016-04-30 5 views
0

Ich habe ein Problem mit diesem Code. Keine Fehler oder Warnungen, aber Dreieck erscheint, wenn Fenster nur die Größe ändert.Triangle Zeichnung mit OpenGL: wie mit zwei Klassen zu verwalten

Ich muss das korrigieren. Header-Datei enthalten diese zwei Klassen: Window und WindowGL (klassenbasierte Vererbung). Was ist mit diesem Code falsch?

#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 

Und CPP-Datei:

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

Antwort

2

Sie rufen Render() nur, wenn WM_PAINT gesendet wird, versuchen Sie es in Run() einmal ein paar Millisekunden jeder zu nennen. Ändern Sie GetMessage mit PeekMessage, um zu verhindern, dass der Code blockiert, und verwenden Sie dann GetMessage nur, wenn eine Nachricht zu lesen ist.

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 
} 

EDIT 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 dafür. Ich habe die Run() -Funktion aktualisiert. Aber immer noch das gleiche Problem. Kein Dreieck, ohne die Fenstergröße zu ändern. –

+0

Ich habe den Code bearbeitet, er sollte dir die richtige Idee geben. – FedeWar

+0

Ja, ich habe meinen obigen Code bearbeitet - und Run() mit der "besseren" Funktion PeekMessage() geändert, aber immer noch keinen Effekt. Header-Klassen werden auf diese Weise erstellt, ich kann nicht einmal Render() in Run() aufrufen. Stattdessen kann ich anrufen: Fenster. Render(), aber es ändert nichts. Der Code stammt aus einem Buch, das von einem Physiker geschrieben wurde, aber der Autor stellt keinen Quellcode zur Verfügung. Können Sie versuchen, dieses Zeug auf Ihrem Computer zu kompilieren? Danke für Ihre Hilfe. –