// This is a part of the Microsoft Foundation Classes C++ library. // Copyright (C) 1992-1998 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #ifdef AFX_CORE2_SEG #pragma code_seg(AFX_CORE2_SEG) #endif #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define new DEBUG_NEW ///////////////////////////////////////////////////////////////////////////// // CMultiDocTemplate construction/destruction CMultiDocTemplate::CMultiDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass) : CDocTemplate(nIDResource, pDocClass, pFrameClass, pViewClass) { ASSERT(m_docList.IsEmpty()); m_hMenuShared = NULL; m_hAccelTable = NULL; m_nUntitledCount = 0; // start at 1 // load resources in constructor if not statically allocated if (!CDocManager::bStaticInit) LoadTemplate(); } void CMultiDocTemplate::LoadTemplate() { CDocTemplate::LoadTemplate(); if (m_nIDResource != 0 && m_hMenuShared == NULL) { HINSTANCE hInst = AfxFindResourceHandle( MAKEINTRESOURCE(m_nIDResource), RT_MENU); m_hMenuShared = ::LoadMenu(hInst, MAKEINTRESOURCE(m_nIDResource)); m_hAccelTable = ::LoadAccelerators(hInst, MAKEINTRESOURCE(m_nIDResource)); } #ifdef _DEBUG // warnings about missing components (don't bother with accelerators) if (m_hMenuShared == NULL) TRACE1("Warning: no shared menu for document template #%d.\n", m_nIDResource); #endif //_DEBUG } CMultiDocTemplate::~CMultiDocTemplate() { #ifdef _DEBUG if (!m_docList.IsEmpty()) TRACE1("Warning: destroying CMultiDocTemplate with %d documents alive.\n", m_docList.GetCount()); #endif // delete shared components if (m_hMenuShared != NULL) ::DestroyMenu(m_hMenuShared); if (m_hAccelTable != NULL) ::FreeResource((HGLOBAL)m_hAccelTable); } ///////////////////////////////////////////////////////////////////////////// // CMultiDocTemplate attributes POSITION CMultiDocTemplate::GetFirstDocPosition() const { return m_docList.GetHeadPosition(); } CDocument* CMultiDocTemplate::GetNextDoc(POSITION& rPos) const { return (CDocument*)m_docList.GetNext(rPos); } ///////////////////////////////////////////////////////////////////////////// // CMultiDocTemplate document management (a list of currently open documents) void CMultiDocTemplate::AddDocument(CDocument* pDoc) { ASSERT_VALID(pDoc); CDocTemplate::AddDocument(pDoc); ASSERT(m_docList.Find(pDoc, NULL) == NULL); // must not be in list m_docList.AddTail(pDoc); } void CMultiDocTemplate::RemoveDocument(CDocument* pDoc) { ASSERT_VALID(pDoc); CDocTemplate::RemoveDocument(pDoc); m_docList.RemoveAt(m_docList.Find(pDoc)); } ///////////////////////////////////////////////////////////////////////////// // CMultiDocTemplate commands CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible) { CDocument* pDocument = CreateNewDocument(); if (pDocument == NULL) { TRACE0("CDocTemplate::CreateNewDocument returned NULL.\n"); AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); return NULL; } ASSERT_VALID(pDocument); BOOL bAutoDelete = pDocument->m_bAutoDelete; pDocument->m_bAutoDelete = FALSE; // don't destroy if something goes wrong CFrameWnd* pFrame = CreateNewFrame(pDocument, NULL); pDocument->m_bAutoDelete = bAutoDelete; if (pFrame == NULL) { AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC); delete pDocument; // explicit delete on error return NULL; } ASSERT_VALID(pFrame); 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 TRACE0("CDocument::OnNewDocument returned FALSE.\n"); pFrame->DestroyWindow(); 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 TRACE0("CDocument::OnOpenDocument returned FALSE.\n"); pFrame->DestroyWindow(); return NULL; } pDocument->SetPathName(lpszPathName); } InitialUpdateFrame(pFrame, pDocument, bMakeVisible); return pDocument; } void CMultiDocTemplate::SetDefaultTitle(CDocument* pDocument) { CString strDocName; if (GetDocString(strDocName, CDocTemplate::docName) && !strDocName.IsEmpty()) { TCHAR szNum[8]; wsprintf(szNum, _T("%d"), m_nUntitledCount+1); strDocName += szNum; } else { // use generic 'untitled' - ignore untitled count VERIFY(strDocName.LoadString(AFX_IDS_UNTITLED)); } pDocument->SetTitle(strDocName); } ///////////////////////////////////////////////////////////////////////////// // CMultiDocTemplate diagnostics #ifdef _DEBUG void CMultiDocTemplate::Dump(CDumpContext& dc) const { CDocTemplate::Dump(dc); dc << "m_hMenuShared = " << (UINT)m_hMenuShared; dc << "\nm_hAccelTable = " << (UINT)m_hAccelTable; dc << "\nm_nUntitledCount = " << m_nUntitledCount; dc << "\nwith " << m_docList.GetCount() << " open documents"; POSITION pos = GetFirstDocPosition(); while (pos != NULL) { CDocument* pDoc = GetNextDoc(pos); dc << "\nwith document " << (void*)pDoc; } dc << "\n"; } void CMultiDocTemplate::AssertValid() const { CDocTemplate::AssertValid(); POSITION pos = GetFirstDocPosition(); while (pos != NULL) { CDocument* pDoc = GetNextDoc(pos); ASSERT_VALID(pDoc); } } #endif //_DEBUG #ifdef AFX_INIT_SEG #pragma code_seg(AFX_INIT_SEG) #endif IMPLEMENT_DYNAMIC(CMultiDocTemplate, CDocTemplate) /////////////////////////////////////////////////////////////////////////////