65.9K
CodeProject is changing. Read more.
Home

Single View in MultiDoc-Application

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.47/5 (13 votes)

Feb 24, 2003

CPOL

1 min read

viewsIcon

77250

Single View in MultiDoc-Application

Single View in MultiDoc-Application

Sometimes it is useful, to have only one single instance of a document view in a multi-doc application.

The procedure for achieving this is quite straight forwarded.  Add a variable of type CMultiDocTemplate* to your application class. Call it m_pTplteOnlyOneView, or give it any name that suits you.  Create a class to view that document type. Call it CViewOnlyOneView, or give it any name that suits you.  In your initializing code of your application (usually InitInstance) add

  m_pTplteOnlyOneView = new CMultiDocTemplate(
                IDR_MAIN_MENU, // use your menu-ID
                RUNTIME_CLASS(CMultiDocAppForm), // use your main frame document class
                RUNTIME_CLASS(CChildFrame),      // use your custom MDI child frame
                RUNTIME_CLASS(CViewOnlyOneView));// use your custom document view
  AddDocTemplate(m_pTplteOnlyOneView);

With the application wizard of Visual Studio add a menu command handler for opening this document. Be sure to add that handler in your application class. Also add a handler for the update command function.

Place following code inside the update command handler. Be sure that you use your variable names and not mine.

void CMultiDocApp::OnUpdateOnlyOneView(CCmdUI* pCmdUI)
{ pCmdUI->Enable(TRUE);
  if( NULL == m_pTplteOnlyOneView ) pCmdUI->Enable(FALSE);
}

Place following code inside the command handler. Be sure that you use your variable names and not mine.

void CMultiDocApp::OnOnlyOneView()
{ ASSERT_VALID(m_pTplteOnlyOneView);
  // There may be only one View of that doc type!
  // Is the template initialized?
  POSITION Pos = m_pTplteOnlyOneView->GetFirstDocPosition();
  if( NULL == Pos ) // No
    { m_pTplteOnlyOneView->OpenDocumentFile(NULL);// Initialize
      return;
    }
  // Is there an entry for that document type?
  CDocument *pDoc = m_pTplteOnlyOneView->GetNextDoc(Pos);
  if( NULL == pDoc )// No
    { m_pTplteOnlyOneView->OpenDocumentFile(NULL);// Initialize
      return;
    }
  // Is the View for that document type initialized?
  Pos = pDoc->GetFirstViewPosition();
  if( NULL == Pos )// No
    { m_pTplteOnlyOneView->OpenDocumentFile(NULL);// Initialize
      return;
    }
  // Exists a view for that document type?
  CView *pView = pDoc->GetNextView(Pos);
  if( NULL == pView )// No
    { m_pTplteOnlyOneView->OpenDocumentFile(NULL);// Create view
      return;
    }
  //Exists a window for that view?
  CWnd *pWnd = pView->GetParent();
  if( NULL == pWnd )//No
    { m_pTplteOnlyOneView->OpenDocumentFile(NULL);// Create view
      return;
    }
  // A View and a window exists. Restore or activate?
  WINDOWPLACEMENT wpl;
  pWnd->GetWindowPlacement(&wpl);
  if( SW_SHOWMINIMIZED  == wpl.showCmd )// Iconized window must be restored
    { wpl.showCmd = SW_RESTORE;
      if( WPF_RESTORETOMAXIMIZED == wpl.flags )
         wpl.showCmd = SW_SHOWMAXIMIZED;
      pWnd->SetWindowPlacement(&wpl);
    }
  else
    { wpl.showCmd = SW_RESTORE; // Bring window to top
      pWnd->SetWindowPlacement(&wpl);
      pWnd->BringWindowToTop();
    }
}
That does the trick.If you want to open this document with a file, provide the filename to the OpenDocumentFile function.  Of course then you also have to take care of the contents of the old view, before filling in a new one.

If you have more document types, where only one view should be allowed, just add another CMultiDocTemplate* variable, another command handler, paste the code and adjust the names.