Multiple-document interface applications will make use of at least one document view pair, but they may also utilise additional documents and views to enable the user to work with more than one document at the same time. Within the client area, each document is displayed within a separate child window. An MDI child window looks much like a typical frame window, except that the MDI child window appears inside an MDI frame window and does not have a menu bar of its own, but instead shares the menu of the MDI frame window. The framework automatically changes the MDI frame menu to represent the currently active MDI child window.
In addition to the 3 classes found in an SDI application, an MDI application must derive a class from CMDIChildWnd which provides the functionality for the Windows multiple document interface (MDI) child window. To make a document different from its parent, the application will also require an additional series of resources other than those associated with the main windows.
As opposed to a Single Document Interface application, a Multiple Document Interface (MDI) application uses the CMultiDocTemplate class which, like the CSingleDocTemplate class, is derived from CdocTemplate.
If the MDI application uses more than one type of document then a separate template must be supplied for each type of document. This will require a separate template for each type of document using a CDocMultiDocTemplate constructor for each.
Working with Multiple-Document Types
By default, an SDI or an MDI application, created with the AppWizard will be configured with only a single document class. Additional document class types can however be added by making a second call to AddDocTemplate() in the application class InitInstance() member function as outlined below-
//Must be compiled using a shared DLL //Microsoft Developer Studio generated resource script. // /* IDR_MDITYPE MENU DISCARDABLE BEGIN POPUP "File" BEGIN MENUITEM "New", ID_FILE_NEW MENUITEM "Open", ID_FILE_OPEN MENUITEM "Close", ID_FILE_CLOSE MENUITEM "Save", ID_FILE_SAVE MENUITEM "Save As", ID_FILE_SAVE_AS MENUITEM "Exit", ID_APP_EXIT END POPUP "Edit" BEGIN MENUITEM "Undo", ID_EDIT_UNDO MENUITEM "Cut", ID_EDIT_CUT MENUITEM "Copy", ID_EDIT_COPY MENUITEM "Paste", ID_EDIT_PASTE END POPUP "Windows" BEGIN MENUITEM "windows", ID_WINDOW_NEW MENUITEM "cascade", ID_WINDOW_CASCADE MENUITEM "Tile", ID_WINDOW_TILE_HORZ MENUITEM "Arrange", ID_WINDOW_ARRANGE END END */ // #include "resource.h" #include <afxext.h> // MFC extensions class CMainFrame : public CMDIFrameWnd { DECLARE_DYNAMIC(CMainFrame) public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); DECLARE_MESSAGE_MAP() }; //child class declaration class CChildFrame : public CMDIChildWnd { DECLARE_DYNCREATE(CChildFrame) public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: DECLARE_MESSAGE_MAP() }; //application class declaration class CMDIApp : public CWinApp { public: afx_msg void OnFileNew(); virtual BOOL InitInstance(); DECLARE_MESSAGE_MAP() }; //document class declaration class CMDIDoc : public CDocument { protected: DECLARE_DYNCREATE(CMDIDoc) public: virtual BOOL OnNewDocument(); virtual void Serialize(CArchive& ar); DECLARE_MESSAGE_MAP() }; //view class declaration class CMDIView : public CEditView { protected: DECLARE_DYNCREATE(CMDIView) DECLARE_MESSAGE_MAP() public: CMDIDoc* GetDocument(); virtual void OnDraw(CDC* pDC); virtual BOOL PreCreateWindow(CREATESTRUCT& cs); }; // enable CObject-derived classes to be created dynamically at run time IMPLEMENT_DYNAMIC(CMainFrame, CMDIFrameWnd) IMPLEMENT_DYNCREATE(CChildFrame, CMDIChildWnd) IMPLEMENT_DYNCREATE(CMDIDoc, CDocument) IMPLEMENT_DYNCREATE(CMDIView, CEditView) //message map frame window BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd) ON_WM_CREATE() END_MESSAGE_MAP() //message map child window BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWnd) END_MESSAGE_MAP() //message map application window BEGIN_MESSAGE_MAP(CMDIApp, CWinApp) ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) END_MESSAGE_MAP() //message map document window BEGIN_MESSAGE_MAP(CMDIDoc, CDocument) END_MESSAGE_MAP() //message map view window BEGIN_MESSAGE_MAP(CMDIView, CEditView) END_MESSAGE_MAP() int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; return 0; } BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { m_strTitle= "MFC MDI"; if( !CMDIFrameWnd::PreCreateWindow(cs) ) return FALSE; return TRUE; } BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CMDIChildWnd::PreCreateWindow(cs) ) return FALSE; return TRUE; } BOOL CMDIDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; SetTitle ("MDI Window"); return TRUE; } void CMDIDoc::Serialize(CArchive& ar) { ((CEditView*)m_viewList.GetHead())->SerializeRaw(ar); } BOOL CMDIView::PreCreateWindow(CREATESTRUCT& cs) { BOOL bPreCreated = CEditView::PreCreateWindow(cs); cs.style &= ~(ES_AUTOHSCROLL|WS_HSCROLL); return bPreCreated; } void CMDIView::OnDraw(CDC* pDC) { CMDIDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); } CMDIDoc* CMDIView::GetDocument() { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMDIDoc))); return (CMDIDoc*)m_pDocument; } BOOL CMDIApp::InitInstance() { LoadStdProfileSettings(); //defines a document template that implements the multi document interface CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_MDITYPE, RUNTIME_CLASS(CMDIDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CMDIView)); CMultiDocTemplate* pDocTemplate1; pDocTemplate1 = new CMultiDocTemplate( IDR_MDITYPE, RUNTIME_CLASS(CMDIDoc), RUNTIME_CLASS(CChildFrame), // custom MDI child frame RUNTIME_CLASS(CMDIView)); AddDocTemplate(pDocTemplate); CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MDITYPE)) return FALSE; m_pMainWnd = pMainFrame; CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); if (!ProcessShellCommand(cmdInfo)) return FALSE; pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE; } CMDIApp theApp;