在 MFC 应用程序中的 OpenGL 视图之间切换

问题描述 投票:0回答:0

此问题是先前发布的问题的后续问题,该问题部分尚未解决。

如何在 MFC SDI 应用程序中切换基于 OpenGL 的视图?

我有一个基于 MFC 的 Windows 桌面 SDI 应用程序,使用 Doc-View 框架构建,并将基于“现代”OpenGL 的图形显示为 MainFrame 中的默认视图。

我希望能够在应用程序运行时通过主菜单选项“切换视图”将应用程序默认视图类切换/切换为备用完全独立的视图类,以便备用视图类成为显示的活动视图.

我可以成功地在两个单独的视图类之间切换活动视图 - 但前提是辅助视图是非基于 OpenGL 的视图类(即使用默认的 Windows GDI 图形)。目前,出于测试目的,辅助视图仅呈现纯白色背景和静态硬编码文本消息,以确认它是所选的视图。

当我切换回 OpenGL 视图时,它完全处于切换之前的状态(即 OpenGL 视图没有“销毁”并保存在内存中)。

但是如果我尝试切换到同样基于 OpenGL 的第二个视图(但使用完全不同的着色器),则程序会崩溃并出现以下错误:

程序此时中断(崩溃):

任何人都可以建议这意味着什么或可能与什么相关吗?

用于在两个视图之间切换的事件处理程序代码如下所示。应用程序默认视图是“ModelView3D”,第二个 OpenGL 视图是“StaticView3D”。如上所述,当“StaticView3D”不使用 OpenGL(即标准 MFC 视图类)时,视图切换工作正常。

CView* CMFCAPPApp::SwitchView()
{
    CView* pActiveView = ((CFrameWnd*)m_pMainWnd)->GetActiveView();

    CView* pNewView = nullptr;

    POSITION  pos = AfxGetApp()->GetFirstDocTemplatePosition();

    CDocTemplate* doc_template = AfxGetApp()->GetNextDocTemplate(pos);

    if(!m_staticView3D)
        m_staticView3D = (CView*) new StaticView3D; 
    if (NULL == m_staticView3D)
        return FALSE;

    // Initialize a CCreateContext to point to the active document.
    // With this context, the new view is added to the document
    // when the view is created in CView::OnCreate().
    CCreateContext newContext;
    newContext.m_pNewViewClass = NULL;
    newContext.m_pNewDocTemplate = doc_template;
    newContext.m_pLastView = NULL;
    newContext.m_pCurrentFrame = NULL;

    //set to NULL if the new View class will not use the Doc object
    newContext.m_pCurrentDoc = NULL;

    // The ID of the initial active view is AFX_IDW_PANE_FIRST.
    // Incrementing this value by one for additional views works
    // in the standard document/view case but the technique cannot
    // be extended for the CSplitterWnd case.
    UINT viewID = AFX_IDW_PANE_FIRST + 1;
    CRect rect(0, 0, 0, 0); // Gets resized later.

    if(!m_staticView3D->GetSafeHwnd())
        m_staticView3D->Create(NULL, _T("StaticView3D"), WS_CHILD | WS_OVERLAPPEDWINDOW, rect, m_pMainWnd, viewID, &newContext); // WS_CHILD

    // When a document template creates a view, the WM_INITIALUPDATE
    // message is sent automatically. However, this code must
    // explicitly send the message, as follows.
    m_staticView3D->SendMessage(WM_INITIALUPDATE, 0, 0);

    if (pActiveView == m_modelView3D)
        pNewView = m_staticView3D;
    else
        pNewView = m_modelView3D;

    // Exchange view window IDs so RecalcLayout() works.
    #ifndef _WIN32
        UINT temp = ::GetWindowWord(pActiveView->m_hWnd, GWW_ID);
        ::SetWindowWord(pActiveView->m_hWnd, GWW_ID, ::GetWindowWord(pNewView->m_hWnd, GWW_ID));
        ::SetWindowWord(pNewView->m_hWnd, GWW_ID, temp);
    #else
        UINT temp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID);
        ::SetWindowLong(pActiveView->m_hWnd, GWL_ID, ::GetWindowLong(pNewView->m_hWnd, GWL_ID));
        ::SetWindowLong(pNewView->m_hWnd, GWL_ID, temp);
    #endif

    pActiveView->ShowWindow(SW_HIDE);
    pNewView->ShowWindow(SW_SHOW);
    ((CFrameWnd*)m_pMainWnd)->SetActiveView(pNewView);
    ((CFrameWnd*)m_pMainWnd)->RecalcLayout();
    pNewView->Invalidate();
    return pActiveView;
}
c++ windows opengl graphics mfc
© www.soinside.com 2019 - 2024. All rights reserved.