Dynamically Create Different Views for SDI Projects





Environment: Any flavour of MFC (Doc/View) including VC6, VC7, and Embedded Visual C++

Sometimes you have an SDI-based project and you do not want to be restricted to a single view (single template). In this article, a piece of code will be presented that will let you change your view of your SDI project dynamically to any other view. In the Windows CE environment, the Visual Embedded Studio does not give you the option of creating MDI projects; this is the perfect alternative for it.

To write this code, I have debugged into the MFC Library and learned few things; I finally took a copy of CSingleDocTemplate::OpenDocumentFile and modified it into a new method called: DynamicOpenDocumentFile(...)

I have Derived a class from CSingleDocTemplate, called CDynamicSingleDocTemplate. It has a new method called DynamicOpenDocumentFile(...) with similar parameters to OpenDocumentFile(...)

CDocument *CDynamicSingleDocTemplate::DynamicOpenDocumentFile
           (LPCTSTR lpszPathName, BOOL bMakeVisible)
{
  // destroy the current view along with its document
  AfxGetMainWnd()->GetDlgItem(AFX_IDW_PANE_FIRST)->DestroyWindow();

  CWinThread* pThread = AfxGetThread();
  pThread->m_pMainWnd = NULL;

  CDocument* pDocument = NULL;
  CFrameWnd* pFrame = NULL;
  BOOL bCreated = FALSE;      // => doc and frame created
  BOOL bWasModified = FALSE;

  if (m_pOnlyDoc != NULL)
  {
    // already have a document -- reinit it
    pDocument = m_pOnlyDoc;
    if (!pDocument->SaveModified())
      return NULL;        // leave the original one

    pFrame = (CFrameWnd*) AfxGetMainWnd();
    ASSERT(pFrame != NULL);
    ASSERT_KINDOF(CFrameWnd, pFrame);
    ASSERT_VALID(pFrame);
  }
  else
  {
    // create a new document
    pDocument = CreateNewDocument();
    ASSERT(pFrame == NULL);     // will be created below
    bCreated = TRUE;
  }

  if (pDocument == NULL)
  {
    AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
    return NULL;
  }
  ASSERT(pDocument == m_pOnlyDoc);

  pFrame = (CFrameWnd*) AfxGetMainWnd();

  // create our view
  CCreateContext context;
  context.m_pCurrentFrame = NULL; // pFrame
  context.m_pCurrentDoc = pDocument;
  context.m_pLastView = NULL;
  context.m_pNewDocTemplate = this;
  context.m_pNewViewClass = m_pViewClass;

  CWnd *pView = pFrame->CreateView(&context);
  if (!pView)
    return NULL;

  if (lpszPathName == NULL)
  {
    // create a new document
    SetDefaultTitle(pDocument);

    // avoid creating temporary compound file when starting
    // up invisible
    if (!bMakeVisible)
      pDocument->m_bEmbedded = TRUE;

    if (!pDocument->OnNewDocument())
    {
      // user has been alerted to what failed in OnNewDocument
      TRACE0("CDocument::OnNewDocument returned FALSE.\n");
      if (bCreated)
        pFrame->DestroyWindow();    // will destroy document
      return NULL;
    }
  }
  else
  {
    CWaitCursor wait;

    // open an existing document
    bWasModified = pDocument->IsModified();
    pDocument->SetModifiedFlag(FALSE);  // not dirty for open

    if (!pDocument->OnOpenDocument(lpszPathName))
    {
      // user has been alerted to what failed in OnOpenDocument
      TRACE0("CDocument::OnOpenDocument returned FALSE.\n");
      if (bCreated)
      {
        pFrame->DestroyWindow();    // will destroy document
      }
      else if (!pDocument->IsModified())
      {
        // original document is untouched
        pDocument->SetModifiedFlag(bWasModified);
      }
      else
      {
        // we corrupted the original document
        SetDefaultTitle(pDocument);

        if (!pDocument->OnNewDocument())
        {
          TRACE0("Error: OnNewDocument failed after trying to open
                 a document - trying to continue.\n");
          // assume we can continue
        }
      }
      return NULL;        // open failed
    }
    pDocument->SetPathName(lpszPathName);
  }

  pThread->m_pMainWnd = pFrame;

  InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
  pFrame->RecalcLayout();

  return pDocument;
}

Downloads

Download demo project - 44 Kb
Download source - 2 Kb