2016-04-30 27 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()。相反,我可以調用:窗口。渲染(),但它不會改變任何東西。代碼來自物理學家編寫的書,但作者不提供源代碼。你可以嘗試在你的機器上編譯這些東西嗎?謝謝你的幫助。 –

相關問題