Click here to Skip to main content
15,892,927 members
Articles / Desktop Programming / MFC

SVDI: a "Single View, Multiple Documents" MFC Architecture

Rate me:
Please Sign up or sign in to vote.
3.73/5 (5 votes)
20 May 20043 min read 74.9K   4.5K   27  
An article on a "Single View, Multiple Documents" MFC Architecture with a new VC++ code wizard
// docmulti2.cpp : implementation of the CSingleViewMultiDocTemplate class
//
#include "stdafx.h"
#include "docmulti2.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// registered message for view creation
UINT _afxMsgCreateView = RegisterWindowMessage(_T("WM_CREATEVIEW"));
// registered message for view update
UINT _afxMsgUpdateView = RegisterWindowMessage(_T("WM_UPDATEVIEW"));


// CSingleViewMultiDocTemplate

CSingleViewMultiDocTemplate::CSingleViewMultiDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
		CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
		: CMultiDocTemplate(nIDResource, pDocClass,
		pFrameClass, pViewClass)
{
}

/////////////////////////////////////////////////////////////////////////////
// CSingleViewMultiDocTemplate commands

CDocument* CSingleViewMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
	BOOL bMakeVisible)
{
	BOOL bCreated = FALSE;      // => view created

	// Document creation
	CDocument* pDocument = CreateNewDocument();
	if (pDocument == NULL)
	{
		TRACE(traceAppMsg, 0, "CDocTemplate::CreateNewDocument returned NULL.\n");
		AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
		return NULL;
	}
	ASSERT_VALID(pDocument);

	// Looking for main frame
	CFrameWnd* pFrame = (CFrameWnd*)AfxGetMainWnd();
	if (pFrame == NULL)
	{
		AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
		delete pDocument;       // explicit delete on error
		return NULL;
	}
	ASSERT_KINDOF(CFrameWnd, pFrame);
	ASSERT_VALID(pFrame);

	// Looking for a view
	CView* pView = (CView*)pFrame->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);

	// Is it a view ?
	if ((pView != NULL) && !pView->IsKindOf(RUNTIME_CLASS(CView)))
		pView = NULL;

	if (pView == NULL)
	{
		// View does not exist, creating it
		pView = CreateNewView(pDocument, pFrame);
		if (!pView)
		{
			AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
			delete pDocument;       // explicit delete on error
			return NULL;
		}
		bCreated = TRUE;

		// make sure the child windows have been properly sized
		pFrame->RecalcLayout();
	}
	else
	{
		// Somme views exist, connect them to new document
		CDocument* pPrevDocument = pView->GetDocument();
		ASSERT(pPrevDocument != NULL);
		POSITION pos = pPrevDocument->GetFirstViewPosition();
		while (pos != NULL) {
			pView = pPrevDocument->GetNextView(pos);
			pPrevDocument->RemoveView(pView);
			pDocument->AddView(pView);
		}
	}

	if (lpszPathName == NULL)
	{
		// create a new document - with default document name
		SetDefaultTitle(pDocument);

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

		if (!pDocument->OnNewDocument())
		{
			// user has be alerted to what failed in OnNewDocument
			TRACE(traceAppMsg, 0, "CDocument::OnNewDocument returned FALSE.\n");
			if (bCreated) {
				// Special case of splitter window
				CSplitterWnd* pSplitter = CView::GetParentSplitter(pView, TRUE);
				if (pSplitter != NULL)
					pSplitter->DestroyWindow();
				else
					pView->DestroyWindow();
			}
			delete pDocument;       // explicit delete on error
			return NULL;
		}

		// it worked, now bump untitled count
		m_nUntitledCount++;
	}
	else
	{
		// open an existing document
		CWaitCursor wait;
		if (!pDocument->OnOpenDocument(lpszPathName))
		{
			// user has be alerted to what failed in OnOpenDocument
			TRACE(traceAppMsg, 0, "CDocument::OnOpenDocument returned FALSE.\n");
			if (bCreated) {
				// Special case of splitter window
				CSplitterWnd* pSplitter = CView::GetParentSplitter(pView, TRUE);
				if (pSplitter != NULL)
					pSplitter->DestroyWindow();
				else
					pView->DestroyWindow();
			}
			delete pDocument;       // explicit delete on error
			return NULL;
		}
		pDocument->SetPathName(lpszPathName);
	}

	InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
	return pDocument;
}

CView* CSingleViewMultiDocTemplate::CreateNewView(CDocument* pDoc, CFrameWnd* pFrame)
{
	if (NULL != pDoc)
		ASSERT_VALID(pDoc);
	ASSERT(pFrame != NULL);

	// create a view wired to the specified document
	CCreateContext context;
	context.m_pCurrentFrame = pFrame;
	context.m_pCurrentDoc = pDoc;
	context.m_pNewViewClass = m_pViewClass;
	context.m_pNewDocTemplate = this;

	// The frame must process this message
	pFrame->SendMessage(_afxMsgCreateView, (WPARAM)&context);

	return (CView*)pFrame->GetDescendantWindow(AFX_IDW_PANE_FIRST, TRUE);
}


IMPLEMENT_DYNAMIC(CSingleViewMultiDocTemplate, CMultiDocTemplate)


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions