Enumerate documents in MDI applications

To enumerate all open documents in MDI (Multiple Document Interface) MFC applications we can do the following:

  1. Use CWinApp::GetFirstDocTemplatePosition and CWinApp::GetNextDocTemplate to get application document templates.
  2. For each document template, use CDocTemplate::GetFirstDocPosition and CDocTemplate::GetNextDoc to get contained documents.

Getting documents list

// MyMDIApp.h
// ...
typedef CTypedPtrList<CObList, CDocument*> DocsPtrList;
// ...
class CMyMDIApp : public CWinApp
{
   // ...
public:
   void GetAllDocuments(DocsPtrList& listDocs);
   // ...
};
// MyMDIApp.cpp
// ...
void CMyMDIApp::GetAllDocuments(DocsPtrList& listDocs)
{
   // clear the list
   listDocs.RemoveAll();
   // loop through application's document templates
   POSITION posDocTemplate = GetFirstDocTemplatePosition();
   while(NULL != posDocTemplate)
   {
      CDocTemplate* pDocTemplate = GetNextDocTemplate(posDocTemplate);

      // get each document open in given document template
      POSITION posDoc = pDocTemplate->GetFirstDocPosition();
      while(NULL != posDoc)
      {
         CDocument* pDoc = pDocTemplate->GetNextDoc(posDoc);
         listDocs.AddTail(pDoc); // add document to list
      }
   }
}

Example using documents list

This example calls CMyMDIApp::GetAllDocuments to get a list of all open documents, then fill a combobox control with document titles.
Also, it keeps the document pointers in each item data for further use (e.g. the application can activate the selected document at user request).

// MoreWindowsDlg.h
//...
class CMoreWindowsDlg : public CDialog
{
   // ...
public:
   virtual BOOL OnInitDialog();
private:
   CListBox m_listDocs;
   void _FillDocumentsListBox();
protected:
   afx_msg void OnBnClickedButtonActivate();
};
// MoreWindowsDlg.cpp
// ...
BOOL CMoreWindowsDlg::OnInitDialog()
{
   CDialog::OnInitDialog();
   _FillDocumentsListBox();
   //...
   return TRUE;
}

void CMoreWindowsDlg::_FillDocumentsListBox()
{
   // reset documents listbox control
   m_listDocs.ResetContent();
   CMyMDIApp* pApp = (CMyMDIApp*)AfxGetApp();
   ASSERT_VALID(pApp);

   // get a list of all open documents
   DocsPtrList listDocs;
   pApp->GetAllDocuments(listDocs);
   POSITION pos = listDocs.GetHeadPosition();
   while(NULL != pos)
   {
      CDocument* pDoc = listDocs.GetNext(pos);
      // add document title to listbox control
      const CString strTitle = pDoc->GetTitle();
      int nPos = m_listDocs.AddString(strTitle);
      // keep in mind the document pointer for further use
      m_listDocs.SetItemData(nPos, (DWORD_PTR)pDoc);
   }
}

void CMoreWindowsDlg::OnBnClickedButtonActivate()
{
   const int nCurSel = m_listDocs.GetCurSel();
   if(LB_ERR != nCurSel)
   {
      // activate the selected document
      CDocument* pDoc = 
         (CDocument*)m_listDocs.GetItemData(nCurSel);
      ASSERT_KINDOF(CDocument, pDoc);
      POSITION pos = pDoc->GetFirstViewPosition();
      if(NULL != pos)
      {
         CView* pView = pDoc->GetNextView(pos);
         CFrameWnd* pFrame = pView->GetParentFrame();
         pFrame->ActivateFrame();
      }
   }
}

Resources

See also

Leave a Comment