doctempl.cpp 12 KB

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