Single View in MultiDoc-Application






4.47/5 (13 votes)
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.