home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / doctempl.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  12KB  |  437 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE2_SEG
  14. #pragma code_seg(AFX_CORE2_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CDocTemplate construction/destruction
  26.  
  27. CDocTemplate::CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass,
  28.     CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass)
  29. {
  30.     ASSERT_VALID_IDR(nIDResource);
  31.     ASSERT(pDocClass == NULL ||
  32.         pDocClass->IsDerivedFrom(RUNTIME_CLASS(CDocument)));
  33.     ASSERT(pFrameClass == NULL ||
  34.         pFrameClass->IsDerivedFrom(RUNTIME_CLASS(CFrameWnd)));
  35.     ASSERT(pViewClass == NULL ||
  36.         pViewClass->IsDerivedFrom(RUNTIME_CLASS(CView)));
  37.  
  38.     m_nIDResource = nIDResource;
  39.     m_nIDServerResource = NULL;
  40.     m_nIDEmbeddingResource = NULL;
  41.     m_nIDContainerResource = NULL;
  42.  
  43.     m_pDocClass = pDocClass;
  44.     m_pFrameClass = pFrameClass;
  45.     m_pViewClass = pViewClass;
  46.     m_pOleFrameClass = NULL;
  47.     m_pOleViewClass = NULL;
  48.  
  49.     m_pAttachedFactory = NULL;
  50.     m_hMenuInPlace = NULL;
  51.     m_hAccelInPlace = NULL;
  52.     m_hMenuEmbedding = NULL;
  53.     m_hAccelEmbedding = NULL;
  54.     m_hMenuInPlaceServer = NULL;
  55.     m_hAccelInPlaceServer = NULL;
  56.  
  57.     // add to pStaticList if constructed as static instead of on heap
  58.     if (CDocManager::bStaticInit)
  59.     {
  60.         m_bAutoDelete = FALSE;
  61.         if (CDocManager::pStaticList == NULL)
  62.             CDocManager::pStaticList = new CPtrList;
  63.         if (CDocManager::pStaticDocManager == NULL)
  64.             CDocManager::pStaticDocManager = new CDocManager;
  65.         CDocManager::pStaticList->AddTail(this);
  66.     }
  67.     else
  68.     {
  69.         m_bAutoDelete = TRUE;   // usually allocated on the heap
  70.         LoadTemplate();
  71.     }
  72. }
  73.  
  74. void CDocTemplate::LoadTemplate()
  75. {
  76.     if (m_strDocStrings.IsEmpty() && !m_strDocStrings.LoadString(m_nIDResource))
  77.     {
  78.         TRACE1("Warning: no document names in string for template #%d.\n",
  79.             m_nIDResource);
  80.     }
  81.  
  82.     if (m_nIDEmbeddingResource != 0 && m_hMenuEmbedding == NULL)
  83.     {
  84.         // load menu to be used while editing an embedding (as a server)
  85.         HINSTANCE hInst = AfxFindResourceHandle(
  86.             MAKEINTRESOURCE(m_nIDEmbeddingResource), RT_MENU);
  87.         m_hMenuEmbedding =
  88.             ::LoadMenu(hInst, MAKEINTRESOURCE(m_nIDEmbeddingResource));
  89.         m_hAccelEmbedding =
  90.             ::LoadAccelerators(hInst, MAKEINTRESOURCE(m_nIDEmbeddingResource));
  91.     }
  92.     if (m_nIDServerResource != 0 && m_hMenuInPlaceServer == NULL)
  93.     {
  94.         // load menu to be used while editing in-place (as a server)
  95.         HINSTANCE hInst = AfxFindResourceHandle(
  96.             MAKEINTRESOURCE(m_nIDServerResource), RT_MENU);
  97.         m_hMenuInPlaceServer = ::LoadMenu(hInst,
  98.             MAKEINTRESOURCE(m_nIDServerResource));
  99.         m_hAccelInPlaceServer = ::LoadAccelerators(hInst,
  100.             MAKEINTRESOURCE(m_nIDServerResource));
  101.     }
  102.  
  103.     if (m_nIDContainerResource != 0 && m_hMenuInPlace == NULL)
  104.     {
  105.         // load menu to be used while in-place editing session (as a container)
  106.         HINSTANCE hInst = AfxFindResourceHandle(
  107.             MAKEINTRESOURCE(m_nIDContainerResource), RT_MENU);
  108.         m_hMenuInPlace = ::LoadMenu(hInst,
  109.             MAKEINTRESOURCE(m_nIDContainerResource));
  110.         m_hAccelInPlace = ::LoadAccelerators(hInst,
  111.             MAKEINTRESOURCE(m_nIDContainerResource));
  112.     }
  113. }
  114.  
  115. void CDocTemplate::SetServerInfo(UINT nIDOleEmbedding, UINT nIDOleInPlaceServer,
  116.     CRuntimeClass* pOleFrameClass, CRuntimeClass* pOleViewClass)
  117. {
  118.     ASSERT_VALID_IDR(nIDOleEmbedding);
  119.     if (nIDOleInPlaceServer != 0)
  120.         ASSERT_VALID_IDR(nIDOleInPlaceServer);
  121.     ASSERT(pOleFrameClass == NULL ||
  122.         pOleFrameClass->IsDerivedFrom(RUNTIME_CLASS(CFrameWnd)));
  123.     ASSERT(pOleViewClass == NULL ||
  124.         pOleViewClass->IsDerivedFrom(RUNTIME_CLASS(CView)));
  125.  
  126.     m_pOleFrameClass = pOleFrameClass;
  127.     m_pOleViewClass = pOleViewClass;
  128.  
  129.     m_nIDEmbeddingResource = nIDOleEmbedding;
  130.     m_nIDServerResource = nIDOleInPlaceServer;
  131.     if (!CDocManager::bStaticInit)
  132.         LoadTemplate();
  133. }
  134.  
  135. void CDocTemplate::SetContainerInfo(UINT nIDOleInPlaceContainer)
  136. {
  137.     ASSERT(nIDOleInPlaceContainer != 0);
  138.  
  139.     m_nIDContainerResource = nIDOleInPlaceContainer;
  140.     if (!CDocManager::bStaticInit)
  141.         LoadTemplate();
  142. }
  143.  
  144. CDocTemplate::~CDocTemplate()
  145. {
  146.     // delete OLE resources
  147.     if (m_hMenuInPlace != NULL)
  148.         ::DestroyMenu(m_hMenuInPlace);
  149.     if (m_hAccelInPlace != NULL)
  150.         ::FreeResource(m_hAccelInPlace);
  151.     if (m_hMenuEmbedding != NULL)
  152.         ::DestroyMenu(m_hMenuEmbedding);
  153.     if (m_hAccelEmbedding != NULL)
  154.         ::FreeResource(m_hAccelEmbedding);
  155.     if (m_hMenuInPlaceServer != NULL)
  156.         ::DestroyMenu(m_hMenuInPlaceServer);
  157.     if (m_hAccelInPlaceServer != NULL)
  158.         ::FreeResource(m_hAccelInPlaceServer);
  159. }
  160.  
  161. /////////////////////////////////////////////////////////////////////////////
  162. // CDocTemplate attributes
  163.  
  164. BOOL CDocTemplate::GetDocString(CString& rString, enum DocStringIndex i) const
  165. {
  166.     return AfxExtractSubString(rString, m_strDocStrings, (int)i);
  167. }
  168.  
  169. /////////////////////////////////////////////////////////////////////////////
  170. // Document management
  171.  
  172. void CDocTemplate::AddDocument(CDocument* pDoc)
  173. {
  174.     ASSERT_VALID(pDoc);
  175.     ASSERT(pDoc->m_pDocTemplate == NULL);   // no template attached yet
  176.     pDoc->m_pDocTemplate = this;
  177. }
  178.  
  179. void CDocTemplate::RemoveDocument(CDocument* pDoc)
  180. {
  181.     ASSERT_VALID(pDoc);
  182.     ASSERT(pDoc->m_pDocTemplate == this);   // must be attached to us
  183.     pDoc->m_pDocTemplate = NULL;
  184. }
  185.  
  186. CDocTemplate::Confidence CDocTemplate::MatchDocType(LPCTSTR lpszPathName,
  187.     CDocument*& rpDocMatch)
  188. {
  189.     ASSERT(lpszPathName != NULL);
  190.     rpDocMatch = NULL;
  191.  
  192.     // go through all documents
  193.     POSITION pos = GetFirstDocPosition();
  194.     while (pos != NULL)
  195.     {
  196.         CDocument* pDoc = GetNextDoc(pos);
  197.         if (AfxComparePath(pDoc->GetPathName(), lpszPathName))
  198.         {
  199.             // already open
  200.             rpDocMatch = pDoc;
  201.             return yesAlreadyOpen;
  202.         }
  203.     }
  204.  
  205.     // see if it matches our default suffix
  206.     CString strFilterExt;
  207.     if (GetDocString(strFilterExt, CDocTemplate::filterExt) &&
  208.       !strFilterExt.IsEmpty())
  209.     {
  210.         // see if extension matches
  211.         ASSERT(strFilterExt[0] == '.');
  212.         LPCTSTR lpszDot = _tcsrchr(lpszPathName, '.');
  213.         if (lpszDot != NULL && lstrcmpi(lpszDot, strFilterExt) == 0)
  214.             return yesAttemptNative; // extension matches, looks like ours
  215.     }
  216.  
  217.     // otherwise we will guess it may work
  218.     return yesAttemptForeign;
  219. }
  220.  
  221. CDocument* CDocTemplate::CreateNewDocument()
  222. {
  223.     // default implementation constructs one from CRuntimeClass
  224.     if (m_pDocClass == NULL)
  225.     {
  226.         TRACE0("Error: you must override CDocTemplate::CreateNewDocument.\n");
  227.         ASSERT(FALSE);
  228.         return NULL;
  229.     }
  230.     CDocument* pDocument = (CDocument*)m_pDocClass->CreateObject();
  231.     if (pDocument == NULL)
  232.     {
  233.         TRACE1("Warning: Dynamic create of document type %hs failed.\n",
  234.             m_pDocClass->m_lpszClassName);
  235.         return NULL;
  236.     }
  237.     ASSERT_KINDOF(CDocument, pDocument);
  238.     AddDocument(pDocument);
  239.     return pDocument;
  240. }
  241.  
  242. /////////////////////////////////////////////////////////////////////////////
  243. // Default frame creation
  244.  
  245. CFrameWnd* CDocTemplate::CreateNewFrame(CDocument* pDoc, CFrameWnd* pOther)
  246. {
  247.     if (pDoc != NULL)
  248.         ASSERT_VALID(pDoc);
  249.     // create a frame wired to the specified document
  250.  
  251.     ASSERT(m_nIDResource != 0); // must have a resource ID to load from
  252.     CCreateContext context;
  253.     context.m_pCurrentFrame = pOther;
  254.     context.m_pCurrentDoc = pDoc;
  255.     context.m_pNewViewClass = m_pViewClass;
  256.     context.m_pNewDocTemplate = this;
  257.  
  258.     if (m_pFrameClass == NULL)
  259.     {
  260.         TRACE0("Error: you must override CDocTemplate::CreateNewFrame.\n");
  261.         ASSERT(FALSE);
  262.         return NULL;
  263.     }
  264.     CFrameWnd* pFrame = (CFrameWnd*)m_pFrameClass->CreateObject();
  265.     if (pFrame == NULL)
  266.     {
  267.         TRACE1("Warning: Dynamic create of frame %hs failed.\n",
  268.             m_pFrameClass->m_lpszClassName);
  269.         return NULL;
  270.     }
  271.     ASSERT_KINDOF(CFrameWnd, pFrame);
  272.  
  273.     if (context.m_pNewViewClass == NULL)
  274.         TRACE0("Warning: creating frame with no default view.\n");
  275.  
  276.     // create new from resource
  277.     if (!pFrame->LoadFrame(m_nIDResource,
  278.             WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,   // default frame styles
  279.             NULL, &context))
  280.     {
  281.         TRACE0("Warning: CDocTemplate couldn't create a frame.\n");
  282.         // frame will be deleted in PostNcDestroy cleanup
  283.         return NULL;
  284.     }
  285.  
  286.     // it worked !
  287.     return pFrame;
  288. }
  289.  
  290. CFrameWnd* CDocTemplate::CreateOleFrame(CWnd* pParentWnd, CDocument* pDoc,
  291.     BOOL bCreateView)
  292. {
  293.     CCreateContext context;
  294.     context.m_pCurrentFrame = NULL;
  295.     context.m_pCurrentDoc = pDoc;
  296.     context.m_pNewViewClass = bCreateView ? m_pOleViewClass : NULL;
  297.     context.m_pNewDocTemplate = this;
  298.  
  299.     if (m_pOleFrameClass == NULL)
  300.     {
  301.         TRACE0("Warning: pOleFrameClass not specified for doc template.\n");
  302.         return NULL;
  303.     }
  304.  
  305.     ASSERT(m_nIDServerResource != 0); // must have a resource ID to load from
  306.     CFrameWnd* pFrame = (CFrameWnd*)m_pOleFrameClass->CreateObject();
  307.     if (pFrame == NULL)
  308.     {
  309.         TRACE1("Warning: Dynamic create of frame %hs failed.\n",
  310.             m_pOleFrameClass->m_lpszClassName);
  311.         return NULL;
  312.     }
  313.  
  314.     // create new from resource (OLE frames are created as child windows)
  315.     if (!pFrame->LoadFrame(m_nIDServerResource,
  316.         WS_CHILD|WS_CLIPSIBLINGS, pParentWnd, &context))
  317.     {
  318.         TRACE0("Warning: CDocTemplate couldn't create an OLE frame.\n");
  319.         // frame will be deleted in PostNcDestroy cleanup
  320.         return NULL;
  321.     }
  322.  
  323.     // it worked !
  324.     return pFrame;
  325. }
  326.  
  327. void CDocTemplate::InitialUpdateFrame(CFrameWnd* pFrame, CDocument* pDoc,
  328.     BOOL bMakeVisible)
  329. {
  330.     // just delagate to implementation in CFrameWnd
  331.     pFrame->InitialUpdateFrame(pDoc, bMakeVisible);
  332. }
  333.  
  334. /////////////////////////////////////////////////////////////////////////////
  335. // CDocTemplate commands and command helpers
  336.  
  337. BOOL CDocTemplate::SaveAllModified()
  338. {
  339.     POSITION pos = GetFirstDocPosition();
  340.     while (pos != NULL)
  341.     {
  342.         CDocument* pDoc = GetNextDoc(pos);
  343.         if (!pDoc->SaveModified())
  344.             return FALSE;
  345.     }
  346.     return TRUE;
  347. }
  348.  
  349.  
  350. void CDocTemplate::CloseAllDocuments(BOOL)
  351. {
  352.     POSITION pos = GetFirstDocPosition();
  353.     while (pos != NULL)
  354.     {
  355.         CDocument* pDoc = GetNextDoc(pos);
  356.         pDoc->OnCloseDocument();
  357.     }
  358. }
  359.  
  360. void CDocTemplate::OnIdle()
  361. {
  362.     POSITION pos = GetFirstDocPosition();
  363.     while (pos != NULL)
  364.     {
  365.         CDocument* pDoc = GetNextDoc(pos);
  366.         ASSERT_VALID(pDoc);
  367.         ASSERT_KINDOF(CDocument, pDoc);
  368.         pDoc->OnIdle();
  369.     }
  370. }
  371.  
  372. BOOL CDocTemplate::OnCmdMsg(UINT nID, int nCode, void* pExtra,
  373.     AFX_CMDHANDLERINFO* pHandlerInfo)
  374. {
  375.     BOOL bReturn;
  376.     CCmdTarget* pFactory = DYNAMIC_DOWNCAST(CCmdTarget, m_pAttachedFactory);
  377.  
  378.     if (nCode == CN_OLE_UNREGISTER && pFactory != NULL)
  379.         bReturn = pFactory->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  380.     else
  381.         bReturn = CCmdTarget::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
  382.  
  383.     return bReturn;
  384. }
  385.  
  386. /////////////////////////////////////////////////////////////////////////////
  387. // CDocTemplate diagnostics
  388.  
  389. #ifdef _DEBUG
  390. void CDocTemplate::Dump(CDumpContext& dc) const
  391. {
  392.     CCmdTarget::Dump(dc);
  393.  
  394.     dc << "m_nIDResource = " << m_nIDResource;
  395.     dc << "\nm_strDocStrings: " << m_strDocStrings;
  396.  
  397.     if (m_pDocClass)
  398.         dc << "\nm_pDocClass = " << m_pDocClass->m_lpszClassName;
  399.     else
  400.         dc << "\nm_pDocClass = NULL";
  401.  
  402.     if (dc.GetDepth() > 0)
  403.     {
  404.         dc << "\ndocument list = {";
  405.         POSITION pos = GetFirstDocPosition();
  406.         while (pos != NULL)
  407.         {
  408.             CDocument* pDoc = GetNextDoc(pos);
  409.             dc << "\ndocument " << pDoc;
  410.         }
  411.         dc << "\n}";
  412.     }
  413.  
  414.     dc << "\n";
  415. }
  416.  
  417. void CDocTemplate::AssertValid() const
  418. {
  419.     CCmdTarget::AssertValid();
  420.  
  421.     POSITION pos = GetFirstDocPosition();
  422.     while (pos != NULL)
  423.     {
  424.         CDocument* pDoc = GetNextDoc(pos);
  425.         ASSERT_VALID(pDoc);
  426.     }
  427. }
  428. #endif //_DEBUG
  429.  
  430. #ifdef AFX_INIT_SEG
  431. #pragma code_seg(AFX_INIT_SEG)
  432. #endif
  433.  
  434. IMPLEMENT_DYNAMIC(CDocTemplate, CCmdTarget)
  435.  
  436. /////////////////////////////////////////////////////////////////////////////
  437.