MFC and OpenGL CView, C++, initialising OpenGL after GLEW

2.3k views Asked by At

I'm relatively (read: very) new to MFC using C++ - I usually just worry about OpenGL.

From what I know writing C++ Win32 with OGL, I need to initialise GLEW before I initialise OpenGL and create window, which requires a dummy window to be used. Cool, dunnit.

In MFC I've derived a CView class, which hold a member OpenGL class.

I've successfully initialised GLEW using a temporary window in OnPreCreateWindow, I've also successfully initialised OpenGL, but alas, with the wrong HWND / HDC.. indeed debugging tells me the HDC held as a member in my OpenGL class is not the one I get in OnDraw from the CDC ?

Wheres my correct HDC for OpenGL? - I need some MFC help! Will I need to update this DC from time to time?

It seems I have a choice of OnInitialUpdate, OnPreCreateWindow, and OnDraw(CDC*) to initialise/update OpenGL with the correct DC.

void CJesseView::OnInitialUpdate()
{
    CView::OnInitialUpdate();
    HDC hDC = GetDC()->m_hDC;
}

This works and initialises GLEW - should I do it elsewhere?

BOOL CJesseView::PreCreateWindow(CREATESTRUCT& cs)
{
    // TODO: Modify the Window class or styles here by modifying
    //  the CREATESTRUCT cs

    /* modify the style of the view / window */
    cs.dwExStyle |= CS_OWNDC;

    /*  OpenGL Set up
        1. Create a faux window
    */
    CString m_ClassName("JesseGLView");

    HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, m_ClassName, m_ClassName, 
                    WS_POPUP, 0, 0, 640, 480, NULL, NULL, cs.hInstance, NULL);

    ::ShowWindow(hwnd, SW_HIDE);    // Don't show the window.

    /* OpenGL Set up    
       2. Initialise Glews extension Library to give us access to OpenGL 4.1 Core
    */
    m_OpenGL = new OpenGL();

    if( ! m_OpenGL->PreInjectGLEW( hwnd ) )
        MessageBox(_T("No OpenGL Niceties - Couldn't initialise GLEW!"), _T("CJesseView"));

    ::DestroyWindow( hwnd );    //Destroy Window now that the extensions are loaded
    hwnd = NULL;

    //..
    return CView::PreCreateWindow(cs);
}

void CJesseView::OnDraw(CDC* pCDC)
{
    CJesseDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);

    // TODO: add draw code for native data here

    BeginScene(0.4, 0.4, 0.8, 1.0);
    // Draw something!
    EndScene();

    //..
    ::SwapBuffers( pCDC->GetSafeHdc() );
}

int CJesseView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;

    // TODO:  Add your specialized creation code here
    m_OpenGL->Create( AfxGetApp()->GetMainWnd()->GetSafeHwnd(), 
                true, 800, 600, 0.1f, 60000.0f ); // VSYNC, 0.1, 60k for near and far

    return 0;
}

And finally my OpenGL::Create() function, well the errors got to be to do with the HWND I pass in sic how I get the HDC..

bool OpenGL::InitOpenGL( HWND hWnd, int sW, int sH, float nearP, float farP, bool vsync )
{
    bool bOk = false;
    bool error = false;

    m_Context = GetDC( hWnd );

    //do some PIXELFORMATDESCRIPTOR and context attrib setup

    bOk = bOk && (m_Renderer = wglCreateContextAttribsARB(m_Context, 0, actualContextAttribs));

    if( ! bOk )
        return false;

    if(! wglMakeCurrent(m_Context, m_Renderer) ) {    
        wglDeleteContext(m_Renderer);
        return false;
    }

    //... other stuff
}
1

There are 1 answers

1
datenwolf On

I need to initialise GLEW before I initialise OpenGL

No. GLEW needs an existing OpenGL context being made current to properly initialize. This is also clearly stated in the GLEW manual. So go ahead and Read The Fine Manual (RTFM), please.

Now for creating an advanced OpenGL context GLEW is of little help. You need to create a proxy OpenGL context first which you use to get the function pointers to the extension wgl… functions. Don't bother with the MFC here. Use the plain Win32 functions for that. It's explained very well here: http://www.opengl.org/wiki/Creating_an_OpenGL_Context_(WGL)#Proper_Context_Creation

Once you got your proper OpenGL context you can use GLEW.