Environment: Any flavour of MFC (Doc/View) including VC6, VC7, and Embedded Visual C++
Sometimes you have an SDI-based project and you do not want to be restricted to a single view (single template). In this article, a piece of code will be presented that will let you change your view of your SDI project dynamically to any other view. In the Windows CE environment, the Visual Embedded Studio does not give you the option of creating MDI projects; this is the perfect alternative for it.
To write this code, I have debugged into the MFC Library and learned few things; I finally took a copy of CSingleDocTemplate::OpenDocumentFile and modified it into a new method called: DynamicOpenDocumentFile(…)
I have Derived a class from CSingleDocTemplate, called CDynamicSingleDocTemplate. It has a new method called DynamicOpenDocumentFile(…) with similar parameters to OpenDocumentFile(…)
CDocument *CDynamicSingleDocTemplate::DynamicOpenDocumentFile
(LPCTSTR lpszPathName, BOOL bMakeVisible)
{
// destroy the current view along with its document
AfxGetMainWnd()->GetDlgItem(AFX_IDW_PANE_FIRST)->DestroyWindow();CWinThread* pThread = AfxGetThread();
pThread->m_pMainWnd = NULL;CDocument* pDocument = NULL;
CFrameWnd* pFrame = NULL;
BOOL bCreated = FALSE; // => doc and frame created
BOOL bWasModified = FALSE;if (m_pOnlyDoc != NULL)
{
// already have a document — reinit it
pDocument = m_pOnlyDoc;
if (!pDocument->SaveModified())
return NULL; // leave the original onepFrame = (CFrameWnd*) AfxGetMainWnd();
ASSERT(pFrame != NULL);
ASSERT_KINDOF(CFrameWnd, pFrame);
ASSERT_VALID(pFrame);
}
else
{
// create a new document
pDocument = CreateNewDocument();
ASSERT(pFrame == NULL); // will be created below
bCreated = TRUE;
}if (pDocument == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return NULL;
}
ASSERT(pDocument == m_pOnlyDoc);pFrame = (CFrameWnd*) AfxGetMainWnd();
// create our view
CCreateContext context;
context.m_pCurrentFrame = NULL; // pFrame
context.m_pCurrentDoc = pDocument;
context.m_pLastView = NULL;
context.m_pNewDocTemplate = this;
context.m_pNewViewClass = m_pViewClass;CWnd *pView = pFrame->CreateView(&context);
if (!pView)
return NULL;if (lpszPathName == NULL)
{
// create a new document
SetDefaultTitle(pDocument);// avoid creating temporary compound file when starting
// up invisible
if (!bMakeVisible)
pDocument->m_bEmbedded = TRUE;if (!pDocument->OnNewDocument())
{
// user has been alerted to what failed in OnNewDocument
TRACE0(“CDocument::OnNewDocument returned FALSE.\n”);
if (bCreated)
pFrame->DestroyWindow(); // will destroy document
return NULL;
}
}
else
{
CWaitCursor wait;// open an existing document
bWasModified = pDocument->IsModified();
pDocument->SetModifiedFlag(FALSE); // not dirty for openif (!pDocument->OnOpenDocument(lpszPathName))
{
// user has been alerted to what failed in OnOpenDocument
TRACE0(“CDocument::OnOpenDocument returned FALSE.\n”);
if (bCreated)
{
pFrame->DestroyWindow(); // will destroy document
}
else if (!pDocument->IsModified())
{
// original document is untouched
pDocument->SetModifiedFlag(bWasModified);
}
else
{
// we corrupted the original document
SetDefaultTitle(pDocument);if (!pDocument->OnNewDocument())
{
TRACE0(“Error: OnNewDocument failed after trying to open
a document – trying to continue.\n”);
// assume we can continue
}
}
return NULL; // open failed
}
pDocument->SetPathName(lpszPathName);
}pThread->m_pMainWnd = pFrame;
InitialUpdateFrame(pFrame, pDocument, bMakeVisible);
pFrame->RecalcLayout();return pDocument;
}