Search code examples
mfcdocview

Bug in CMDIClientAreaWnd::EnableMDITabs()? recursive call


I use LoadMDIState() in CMyApp::Initintance() to load/restore previous MDI-Doc's window positions.

if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew)
{
    if (!pMainFrame->LoadMDIState(GetRegSectionPath()))
    {
        m_pStartDocTemplate->OpenDocumentFile(NULL);    // Load previous Document
    }
}

It works if his internal state during Serialize() is set to

CMDIClientAreaWnd::m_bTabIsEnabled = FALSE;

But It crashes if son internal state is

CMDIClientAreaWnd::m_bTabIsEnabled = TRUE;

I have investigate this bug in MFC source codes, and see a recursive calls in

void CMDIClientAreaWnd::EnableMDITabs(BOOL bEnable, const CMDITabInfo& params)
{
  if (m_bIsMDITabbedGroup)
  {
    EnableMDITabbedGroups(FALSE, params);
  }
  :
}


void CMDIClientAreaWnd::EnableMDITabbedGroups(BOOL bEnable, const CMDITabInfo& mdiTabParams)
{
  if (m_bTabIsEnabled)
  {
    EnableMDITabs(FALSE, mdiTabParams);
  }
  :
}

Is this a bug? And how to solve this problem for the MDI tabbed Views?


Solution

  • Solved by the comment in MFC source code itself.

    CMDIChildWndEx* CMainFrame::CreateDocumentWindow(LPCTSTR lpcszDocName, CObject* pObj)
    {
      return CMDIFrameWndEx::CreateDocumentWindow(lpcszDocName, pObj);
      ASSERT(FALSE);
      TRACE0("If you use save/load state for MDI tabs, you must override this method in a derived class!\n");
      return NULL;
    }
    

    I have overrided this in CMainframe, and it works.

    CMDIChildWndEx* CMainFrame::CreateDocumentWindow(LPCTSTR lpcszDocName, CObject* pObj)
    {
        CDocument* pDoc = NULL;
        pDoc = AfxGetApp()->OpenDocumentFile(lpcszDocName);
    
        if (pDoc != NULL)
        {
            POSITION pos = pDoc->GetFirstViewPosition();
    
            if (pos != NULL)
            {
                CView* pView = pDoc->GetNextView(pos);
                return DYNAMIC_DOWNCAST(CMDIChildWndEx, pView->GetParent());
            }
        }
    }
    
    return NULL;