3D C/C++ tutorials - OpenGL 1.5 - MFC OpenGL Window
3D C/C++ tutorials -> OpenGL 1.5 -> MFC OpenGL Window
Use for personal or educational purposes only. Commercial and other profit uses strictly prohibited. Exploitation of content on a website or in a publication prohibited.
To compile and run these tutorials some or all of these libraries are required: FreeImage 3.16.0, GLEW 1.11.0, GLUT 3.7.6 / GLUT for Dev-C++, GLM 0.9.5.4
mfc_opengl_window.h
#include <afxwin.h>

#include <gl/glew.h> // http://glew.sourceforge.net/
#include <gl/wglew.h>

// ----------------------------------------------------------------------------------------------------------------------------

#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment(lib, "glew32.lib")

// ----------------------------------------------------------------------------------------------------------------------------

extern CString ErrorLog;

// ----------------------------------------------------------------------------------------------------------------------------

class COpenGLRenderer
{
protected:
    int Width, Height;

public:
    COpenGLRenderer();
    ~COpenGLRenderer();

    bool Init();
    void Render(float FrameTime);
    void Resize(int Width, int Height);
    void Destroy();
};

// ----------------------------------------------------------------------------------------------------------------------------

class CMyWnd : public CWnd
{
protected:
    CString Title;
    HGLRC hGLRC;
    int Width, Height;

public:
    CMyWnd();
    ~CMyWnd();

    void Show(bool Maximized = false);

DECLARE_MESSAGE_MAP()
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnDestroy();
    afx_msg void OnPaint();
    afx_msg void OnSize(UINT nType, int cx, int cy);
};

// ----------------------------------------------------------------------------------------------------------------------------

class CMyWinApp : public CWinApp
{
public:
    CMyWinApp();
    ~CMyWinApp();

    virtual BOOL InitInstance();
};
mfc_opengl_window.cpp
#include "mfc_opengl_window.h"

// ----------------------------------------------------------------------------------------------------------------------------

COpenGLRenderer::COpenGLRenderer()
{
}

COpenGLRenderer::~COpenGLRenderer()
{
}

bool COpenGLRenderer::Init()
{
    return true;
}

void COpenGLRenderer::Render(float FrameTime)
{
    glClear(GL_COLOR_BUFFER_BIT);

    glBegin(GL_TRIANGLES);
        glColor3f(1.0f, 0.0f, 0.0); glVertex2f(-0.5f, -0.5f);
        glColor3f(0.0f, 1.0f, 0.0); glVertex2f( 0.5f, -0.5f);
        glColor3f(0.0f, 0.0f, 1.0); glVertex2f( 0.0f,  0.5f);
    glEnd();
}

void COpenGLRenderer::Resize(int Width, int Height)
{
    this->Width = Width;
    this->Height = Height;

    glViewport(0, 0, Width, Height);
}

void COpenGLRenderer::Destroy()
{
}

// ----------------------------------------------------------------------------------------------------------------------------

COpenGLRenderer OpenGLRenderer;

// ----------------------------------------------------------------------------------------------------------------------------

CString ErrorLog;

// ----------------------------------------------------------------------------------------------------------------------------

BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
    ON_WM_CREATE()
    ON_WM_DESTROY()
    ON_WM_PAINT()
    ON_WM_SIZE()
END_MESSAGE_MAP()

// ----------------------------------------------------------------------------------------------------------------------------

CMyWnd::CMyWnd()
{
}

CMyWnd::~CMyWnd()
{
}

void CMyWnd::Show(bool Maximized)
{
    RECT dRect, wRect, cRect;

    ::GetWindowRect(*GetDesktopWindow(), &dRect);
    GetWindowRect(&wRect);
    GetClientRect(&cRect);

    wRect.right += Width - cRect.right;
    wRect.bottom += Height - cRect.bottom;
    wRect.right -= wRect.left;
    wRect.bottom -= wRect.top;
    wRect.left = dRect.right / 2 - wRect.right / 2;
    wRect.top = dRect.bottom / 2 - wRect.bottom / 2;

    MoveWindow(wRect.left, wRect.top, wRect.right, wRect.bottom, FALSE);

    ShowWindow(Maximized ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL);
}

int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if(CWnd::OnCreate(lpCreateStruct) == -1)
    {
        return -1;
    }

    Title = lpCreateStruct->lpszName;
    Width = lpCreateStruct->cx;
    Height = lpCreateStruct->cy;

    CDC *cDC = GetDC();

    if(cDC == NULL)
    {
        ErrorLog.SetString("GetDC failed!");
        return -1;
    }

    PIXELFORMATDESCRIPTOR pfd;

    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));

    pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.iLayerType = PFD_MAIN_PLANE;

    int PixelFormat = ChoosePixelFormat(*cDC, &pfd);

    if(PixelFormat == 0)
    {
        ErrorLog.SetString("ChoosePixelFormat failed!");
        return -1;
    }

    if(SetPixelFormat(*cDC, PixelFormat, &pfd) == FALSE)
    {
        ErrorLog.SetString("SetPixelFormat failed!");
        return -1;
    }

    hGLRC = wglCreateContext(*cDC);

    if(hGLRC == NULL)
    {
        ErrorLog.SetString("wglCreateContext failed!");
        return -1;
    }

    if(wglMakeCurrent(*cDC, hGLRC) == FALSE)
    {
        ErrorLog.SetString("wglMakeCurrent failed!");
        return -1;
    }

    if(glewInit() != GLEW_OK)
    {
        ErrorLog.SetString("glewInit failed!");
        return -1;
    }

    if(WGLEW_EXT_swap_control)
    {
        wglSwapIntervalEXT(0);
    }

    if(OpenGLRenderer.Init() == false)
    {
        return -1;
    }

    return 0;
}

void CMyWnd::OnDestroy()
{
    OpenGLRenderer.Destroy();
    wglDeleteContext(hGLRC);
}

void CMyWnd::OnPaint()
{
    CPaintDC dc(this);

    static DWORD LastFPSTime = GetTickCount(), LastFrameTime = LastFPSTime;
    static int FPS = 0;

    DWORD Time = GetTickCount();

    float FrameTime = (Time - LastFrameTime) * 0.001f;

    LastFrameTime = Time;

    if(Time - LastFPSTime > 1000)
    {
        CString Text = Title;

        Text.AppendFormat(" - %dx%d", Width, Height);
        Text.AppendFormat(", FPS: %d", FPS);
        Text.AppendFormat(" - %s", (char*)glGetString(GL_RENDERER));
        
        SetWindowText(Text);

        LastFPSTime = Time;
        FPS = 0;
    }
    else
    {
        FPS++;
    }

    OpenGLRenderer.Render(FrameTime);

    SwapBuffers(dc);

    Invalidate(FALSE);
}

void CMyWnd::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);

    Width = cx;
    Height = cy;

    OpenGLRenderer.Resize(Width, Height);
}

// ----------------------------------------------------------------------------------------------------------------------------

CMyWnd MyWnd;

// ----------------------------------------------------------------------------------------------------------------------------

CMyWinApp::CMyWinApp()
{
}

CMyWinApp::~CMyWinApp()
{
}

BOOL CMyWinApp::InitInstance()
{
    LPCTSTR WindowClassName = AfxRegisterWndClass(CS_OWNDC | CS_HREDRAW | CS_VREDRAW, ::LoadCursor(NULL, IDC_ARROW), 0, ::LoadIcon(NULL, IDI_APPLICATION));

    char *AppName = "MFC OpenGL Window";
    DWORD Style = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
    int Width = 800, Height = 600;

    if(MyWnd.CreateEx(WS_EX_APPWINDOW, WindowClassName, AppName, Style, 0, 0, Width, Height, NULL, 0) == FALSE)
    {
        MessageBox(NULL, ErrorLog, AppName, MB_OK | MB_ICONERROR);
        return FALSE;
    }

    MyWnd.Show();

    m_pMainWnd = &MyWnd;

    return TRUE;
}

// ----------------------------------------------------------------------------------------------------------------------------

CMyWinApp MyWinApp;
Download
mfc_opengl_window.zip (Visual Studio 2005 Professional)
© 2010 - 2016 Bc. Michal Belanec, michalbelanec@centrum.sk
Last update June 25, 2016
OpenGL® is a registered trademark of Silicon Graphics Inc.