|
|
1.1 root 1: // This is a part of the Microsoft Foundation Classes C++ library.
2: // Copyright (C) 1992 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 Microsoft
7: // QuickHelp documentation provided with the library.
8: // See these sources for detailed information regarding the
9: // Microsoft Foundation Classes product.
10:
11: #include "oclient.h"
12: #include "mainwnd.h"
13: #include "itemwnd.h"
14:
15: #include <afxdlgs.h>
16:
17: /////////////////////////////////////////////////////////////////////////////
18: // File menu commands
19:
20: void CMainWnd::OnFileNew()
21: {
22: if (!SaveAsNeeded())
23: return;
24:
25: InitFile(FALSE);
26: }
27:
28: void CMainWnd::OnFileOpen()
29: {
30: if (!SaveAsNeeded())
31: return;
32:
33: CString newName = m_fileName;
34: if (!DoFileDlg(newName, IDS_OPENFILE, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST))
35: return;
36:
37: CFile file;
38: if (!file.Open(newName, CFile::modeRead | CFile::shareDenyWrite))
39: {
40: ErrorMessage(E_FAILED_TO_READ_FILE);
41: return;
42: }
43:
44: /* Deregister the current document, and re-init */
45: m_fileName = newName;
46: InitFile(TRUE);
47:
48: /* If we failed to read, we already destroyed
49: * all the objects, so go back to File New-like state */
50: Hourglass(TRUE);
51: TRY
52: {
53: CArchive loadArchive(&file, CArchive::load);
54: this->Serialize(loadArchive); // load me
55: }
56: CATCH (CException, e)
57: {
58: Hourglass(FALSE);
59: ErrorMessage(E_FAILED_TO_READ_FILE);
60: InitFile(FALSE); // just re-init it like New
61: file.Close();
62: return;
63: }
64: END_CATCH
65:
66: Hourglass(FALSE);
67: m_fDirty = FALSE;
68: file.Close();
69: }
70:
71:
72: void CMainWnd::OnFileSave()
73: {
74: // do the save
75: DoSave(m_fileName);
76: }
77:
78:
79: void CMainWnd::OnFileSaveAs()
80: {
81: // save to new name
82: DoSave(NULL);
83: }
84:
85: /////////////////////////////////////////////////////////////////////////////
86: // Basic file operations
87:
88: void CMainWnd::InitFile(BOOL fOpen)
89: {
90: m_fDirty = FALSE;
91:
92: /* If New, reset the file name */
93: if (!fOpen)
94: m_fileName.Empty();
95:
96: /* Deregister the edited document, and wipe out the objects. */
97: DeregisterDoc();
98:
99: /* Reset the title bar, and register the OLE client document */
100: SetTitle();
101: }
102:
103: static void FormatString1(CString&s, UINT idFormat,
104: const char* szData, const char* szAlternate)
105: {
106: char szTmp[CBMESSAGEMAX];
107: CString format;
108: format.LoadString(idFormat);
109:
110: if (szData[0] == '\0')
111: szData = szAlternate;
112:
113: wsprintf(szTmp, (LPCSTR)format, (LPCSTR)szData);
114: s = szTmp;
115: }
116:
117: BOOL CMainWnd::SaveAsNeeded()
118: {
119: if (!m_fDirty)
120: return TRUE;
121:
122: CString prompt;
123: FormatString1(prompt, IDS_MAYBESAVE, m_fileName, strUntitled);
124:
125: /* Ask "Do you wish to save your changes?" */
126: switch (MessageBox(prompt, AfxGetAppName(), MB_YESNOCANCEL | MB_ICONQUESTION))
127: {
128: case IDCANCEL:
129: return FALSE; // don't continue
130: break;
131:
132: case IDYES:
133: /* If so, either Save or Update, as appropriate. */
134: if (!DoSave(m_fileName))
135: return FALSE; // don't continue
136: break;
137:
138: case IDNO:
139: /* If not saving changes, revert the document */
140: m_document.NotifyRevert();
141: break;
142:
143: default:
144: ASSERT(FALSE);
145: break;
146: }
147: return TRUE; // keep going
148: }
149:
150: BOOL CMainWnd::DoSave(const char* szFileName)
151: // note: can be different than 'm_fileName' for SaveAs
152: // will set 'm_fileName' if successful
153: {
154: CString newName = szFileName;
155: if (newName.IsEmpty())
156: {
157: // no file name, prompt for new one
158: if (!DoFileDlg(newName, IDS_SAVEFILE,
159: OFN_HIDEREADONLY | OFN_PATHMUSTEXIST))
160: return FALSE;
161: }
162:
163: CFile file;
164: if (!file.Open(newName, CFile::modeCreate |
165: CFile::modeReadWrite | CFile::shareExclusive))
166: {
167: ErrorMessage(E_INVALID_FILENAME);
168: return FALSE;
169: }
170:
171: Hourglass(TRUE);
172: TRY
173: {
174: CArchive saveArchive(&file, CArchive::store);
175: this->Serialize(saveArchive); // save me
176: }
177: CATCH (CException, e)
178: {
179: Hourglass(FALSE);
180: ErrorMessage(E_FAILED_TO_SAVE_FILE);
181: file.Close();
182: return FALSE;
183: }
184: END_CATCH
185:
186: Hourglass(FALSE);
187: file.Close();
188:
189: // notify library
190: m_document.NotifySaved();
191: m_fDirty = FALSE;
192:
193: // Reset the title and change the document name
194: m_fileName = newName;
195: SetTitle();
196:
197: return TRUE; // success
198: }
199:
200: /////////////////////////////////////////////////////////////////////////////
201: // Actual reading/writing of data
202:
203: void CMainWnd::Serialize(CArchive& ar)
204: {
205: CFrameWnd::Serialize(ar); // does nothing I hope
206: WORD wMagic = 0x0DAF;
207:
208: if (ar.IsStoring())
209: {
210: ar << wMagic;
211: // First count up number of OLE Objects to write
212: CItemWnd* pItemWnd;
213: WORD cCompleteObjectsToWrite = 0;
214: WORD cIncompleteObjects = 0;
215:
216: for (pItemWnd = (CItemWnd*)GetTopWindow(); pItemWnd != NULL;
217: pItemWnd = (CItemWnd*)pItemWnd->GetNextWindow())
218: {
219: if (pItemWnd->IsComplete())
220: cCompleteObjectsToWrite++;
221: else
222: cIncompleteObjects++;
223: }
224:
225: TRACE("%d complete objects to write, %d incomplete ones to ignore\n",
226: cCompleteObjectsToWrite, cIncompleteObjects);
227:
228: CString prompt;
229: prompt.LoadString(IDS_SAVEINCOMPLETE);
230: if (cIncompleteObjects > 0 && MessageBox(prompt, AfxGetAppName(),
231: MB_YESNO | MB_ICONQUESTION) != IDYES)
232: {
233: TRACE("Aborting save\n");
234: AfxThrowArchiveException(CArchiveException::generic);
235: }
236:
237: ar << cCompleteObjectsToWrite;
238:
239: #ifdef _DEBUG
240: WORD cObjectsWritten = 0;
241: #endif
242: // reverse order (easier to rebuild that way)
243: for (pItemWnd = (CItemWnd*)GetTopWindow(); pItemWnd != NULL;
244: pItemWnd = (CItemWnd*)pItemWnd->GetNextWindow())
245: {
246: if (pItemWnd->IsComplete())
247: {
248: pItemWnd->Serialize(ar);
249: // NOTE: don't use WriteObject since we know the actual
250: // class for pItemWnd
251: #ifdef _DEBUG
252: cObjectsWritten++;
253: #endif
254: }
255: }
256: #ifdef _DEBUG
257: ASSERT(cObjectsWritten == cCompleteObjectsToWrite);
258: #endif
259: }
260: else // loading
261: {
262: WORD w;
263: ar >> w;
264:
265: if (w != wMagic)
266: {
267: TRACE("invalid magic number at start of file\n");
268: AfxThrowArchiveException(CArchiveException::generic);
269: }
270:
271: WORD cObjectsToRead;
272: ar >> cObjectsToRead;
273:
274: for (UINT iObj = 0; iObj < cObjectsToRead; iObj++)
275: {
276: CItemWnd* pItemWnd = new CItemWnd(this);
277:
278: pItemWnd->Serialize(ar);
279: }
280: }
281: }
282:
283:
284: /////////////////////////////////////////////////////////////////////////////
285:
286: void CMainWnd::SetTitle()
287: {
288: const char* pszName;
289: char szTitle[CBMESSAGEMAX + _MAX_PATH];
290:
291: pszName = (m_fileName.IsEmpty()) ? strUntitled : m_fileName;
292: wsprintf(szTitle, "%s - %s", (LPCSTR)AfxGetAppName(), (LPCSTR)pszName);
293:
294: /* Perform the client document registration */
295: if (m_document.IsOpen())
296: {
297: m_document.NotifyRename(pszName);
298: }
299: else
300: {
301: if (!m_document.Register(AfxGetAppName(), pszName))
302: {
303: ErrorMessage(W_FAILED_TO_NOTIFY);
304: ASSERT(!m_document.IsOpen());
305: }
306: }
307:
308: SetWindowText(szTitle);
309: }
310:
311: void CMainWnd::DeregisterDoc()
312: {
313: /* Destroy all the objects */
314: ClearAll();
315:
316: /* Release the document */
317: if (m_document.IsOpen())
318: {
319: m_document.Revoke();
320: }
321: }
322:
323: /////////////////////////////////////////////////////////////////////////////
324: // File Dialog prompts
325:
326: static void Normalize(LPSTR lpstrFile);
327:
328: BOOL CMainWnd::DoFileDlg(CString& fileName, UINT nIDTitle, DWORD lFlags)
329: {
330: CString title;
331: CString filter;
332: CString ext;
333: VERIFY(title.LoadString(nIDTitle));
334: VERIFY(filter.LoadString(IDS_FILTER));
335: VERIFY(ext.LoadString(IDS_EXTENSION));
336:
337:
338: CFileDialog dlg(TRUE, ext, fileName, lFlags, filter);
339:
340: dlg.m_ofn.lpstrTitle = title;
341:
342: if (dlg.DoModal() == IDCANCEL)
343: return FALSE;
344:
345: fileName = dlg.GetFileName() + '.' + dlg.GetFileExt();
346: return TRUE;
347: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.