|
|
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: // MAINWND.CXX : main window
12:
13: #include "oclient.h"
14: #include "mainwnd.h"
15: #include "itemwnd.h"
16:
17: static LPSTR CreateNewUniqueName(LPSTR lpstr);
18:
19: /////////////////////////////////////////////////////////////////////////////
20:
21:
22: #pragma warning(disable:4355)
23: // C4355 is "'this' used in base initializer list" warning
24:
25: CMainWnd::CMainWnd()
26: : m_document(this)
27: {
28: VERIFY(m_title.LoadString(IDS_APPNAME));
29: VERIFY(LoadAccelTable(MAKEINTRESOURCE(ID_APPLICATION)));
30: Create(NULL, m_title, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
31: rectDefault, NULL, MAKEINTRESOURCE(ID_APPLICATION));
32: ASSERT(m_hWnd != NULL);
33: m_pSelection = NULL;
34: m_fDirty = FALSE;
35: }
36:
37: #pragma warning(default:4355)
38:
39: // Iterator over content
40: COleClientItem* CMainDocument::GetNextItem(POSITION& rPosition,
41: BOOL* pIsSelected)
42: {
43: CItemWnd* pItemWnd = (CItemWnd*) rPosition;
44: if (pItemWnd == NULL)
45: pItemWnd = (CItemWnd*)m_pView->GetTopWindow();
46: else
47: pItemWnd = (CItemWnd*)pItemWnd->GetNextWindow();
48:
49: *pIsSelected = (m_pView->GetSelection() == pItemWnd);
50: rPosition = (POSITION)pItemWnd;
51: return (pItemWnd == NULL) ? NULL : pItemWnd->GetEmbedded();
52: }
53:
54:
55: /////////////////////////////////////////////////////////////////////////////
56:
57: void CMainWnd::OnAbout()
58: {
59: CModalDialog about(MAKEINTRESOURCE(IDDT_ABOUT), this);
60: about.DoModal();
61: }
62:
63: void CMainWnd::Hourglass(BOOL bOn)
64: {
65: static int count = 0;
66: static HCURSOR hcurWait = AfxGetApp()->LoadStandardCursor(IDC_WAIT);
67: static HCURSOR hcurLast;
68:
69: ASSERT(hcurWait != NULL);
70: if (bOn)
71: {
72: if (count++ == 0)
73: hcurLast = ::SetCursor(hcurWait);
74: }
75: else
76: {
77: if (--count == 0)
78: ::SetCursor(hcurLast);
79: }
80: }
81:
82: void CMainWnd::OnClose()
83: {
84: if (COleClientItem::InWaitForRelease())
85: {
86: ErrorMessage(E_BUSY);
87: return;
88: }
89:
90: if (!SaveAsNeeded())
91: return; // don't quit
92:
93: DeregisterDoc();
94: DestroyWindow();
95: }
96:
97: BOOL CMainWnd::OnQueryEndSession()
98: {
99: if (COleClientItem::InWaitForRelease())
100: return FALSE;
101: return CFrameWnd::OnQueryEndSession();
102: }
103:
104: void CMainWnd::OnDestroy()
105: {
106: GetDocument()->Revoke(); // revoke just in case
107: CFrameWnd::OnDestroy(); // will close down the app
108: }
109:
110: /////////////////////////////////////////////////////////////////////////////
111: // Error reporting
112:
113: void CMainWnd::ErrorMessage(UINT id)
114: {
115: // if in exit mode no message box
116: if (!GetDocument()->IsOpen())
117: return;
118:
119: CString str;
120: str.LoadString(id);
121: MessageBox(str, AfxGetAppName(), MB_OK | MB_ICONEXCLAMATION);
122: }
123:
124: /////////////////////////////////////////////////////////////////////////////
125:
126: void CMainWnd::OnExit()
127: {
128: // close window - NOTE: Do _not_ call 'OnClose' message map function
129: SendMessage(WM_CLOSE);
130: }
131:
132: /////////////////////////////////////////////////////////////////////////////
133:
134:
135: BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
136: // windows messages
137: ON_WM_INITMENUPOPUP()
138: ON_WM_CLOSE()
139: ON_WM_DESTROY()
140: ON_WM_QUERYENDSESSION()
141: ON_WM_ACTIVATE()
142:
143: // file menu commands
144: ON_COMMAND(IDM_NEW, OnFileNew)
145: ON_COMMAND(IDM_OPEN, OnFileOpen)
146: ON_COMMAND(IDM_SAVE, OnFileSave)
147: ON_COMMAND(IDM_SAVEAS, OnFileSaveAs)
148: ON_COMMAND(IDM_EXIT, OnExit)
149: ON_COMMAND(IDM_ABOUT, OnAbout)
150: // edit menu commands
151: ON_COMMAND(IDM_CUT, OnCut)
152: ON_COMMAND(IDM_COPY, OnCopy)
153: ON_COMMAND(IDM_PASTE, OnPaste)
154: ON_COMMAND(IDM_PASTELINK, OnPasteLink)
155: ON_COMMAND(IDM_CLEAR, OnClear)
156: ON_COMMAND(IDM_CLEARALL, OnClearAll)
157: ON_COMMAND(IDM_INSERT_OBJECT, OnInsertObject)
158: ON_COMMAND(IDM_LINKS, OnEditLinks)
159: END_MESSAGE_MAP()
160:
161:
162: /////////////////////////////////////////////////////////////////////////////
163: // Most Edit Commands
164:
165: void CMainWnd::OnInitMenuPopup(CMenu* pMenu, UINT iMenu, BOOL bSysMenu)
166: {
167: if (bSysMenu || iMenu != IMENU_EDIT)
168: return; // system and file menu don't do any dynamic updating
169:
170: ASSERT(pMenu != NULL);
171: // only enable/diable items on the Edit menu
172: CItemWnd* pSelection = GetSelection();
173:
174: //BLOCK: Simple editing
175: {
176: UINT mfCanEdit = MF_GRAYED|MF_DISABLED;
177:
178: if (pSelection != NULL)
179: mfCanEdit = MF_ENABLED; // have some content
180:
181: // Now enable appropriate menu items
182: pMenu->EnableMenuItem(IDM_CUT, mfCanEdit);
183: pMenu->EnableMenuItem(IDM_COPY, mfCanEdit);
184: pMenu->EnableMenuItem(IDM_CLEAR, mfCanEdit);
185: pMenu->EnableMenuItem(IDM_CLEARALL, mfCanEdit);
186: }
187:
188: //BLOCK: paste variants
189: {
190: pMenu->EnableMenuItem(IDM_PASTE, COleClientItem::CanPaste() ?
191: MF_ENABLED : (MF_GRAYED|MF_DISABLED));
192: pMenu->EnableMenuItem(IDM_PASTELINK, COleClientItem::CanPasteLink() ?
193: MF_ENABLED : (MF_GRAYED|MF_DISABLED));
194: }
195:
196: //BLOCK: special case if any linked objects
197: {
198: UINT mfLinks = MF_GRAYED|MF_DISABLED;
199:
200: CItemWnd* pItemWnd;
201: for (pItemWnd = (CItemWnd*)GetTopWindow(); pItemWnd != NULL;
202: pItemWnd = (CItemWnd*)pItemWnd->GetNextWindow())
203: {
204: if (pItemWnd->GetEmbedded()->GetType() == OT_LINK)
205: {
206: mfLinks = MF_ENABLED;
207: break;
208: }
209: }
210: pMenu->EnableMenuItem(IDM_LINKS, mfLinks);
211: }
212:
213: //BLOCK: Object menu specific
214: {
215: static int iItemObjectVerb = -1; // position on the Edit menu
216:
217: if (iItemObjectVerb == -1)
218: {
219: // one-time init - find the position of the "Object ?" menuitem
220: int nItems = pMenu->GetMenuItemCount();
221: for (int iItem = 0; iItem < nItems; iItem++)
222: {
223: if (pMenu->GetMenuItemID(iItem) == IDM_OBJECT_VERB_MIN)
224: {
225: iItemObjectVerb = iItem;
226: break;
227: }
228: }
229: ASSERT(iItemObjectVerb != -1);
230: // MUST BE IN THE MENU TEMPLATE ON INIT !
231: }
232:
233: AfxOleSetEditMenu(pSelection == NULL ? NULL : pSelection->GetEmbedded(),
234: pMenu, iItemObjectVerb, IDM_OBJECT_VERB_MIN);
235: }
236: }
237:
238: BOOL CMainWnd::OnCommand(UINT wParam, LONG lParam)
239: {
240: // if we are waiting for release - ignore all commands
241: if (COleClientItem::InWaitForRelease())
242: {
243: ErrorMessage(E_BUSY);
244: return TRUE; // handled
245: }
246:
247: if (LOWORD(lParam) == 0 && wParam >= IDM_OBJECT_VERB_MIN &&
248: wParam <= IDM_OBJECT_VERB_MAX)
249: {
250: // activate the current selection with the appropriate verb
251: CItemWnd* pItemWnd = GetSelection();
252: ASSERT(pItemWnd != NULL);
253: pItemWnd->DoVerb(wParam - IDM_OBJECT_VERB_MIN);
254: return TRUE; // handled
255: }
256: return CFrameWnd::OnCommand(wParam, lParam);
257: }
258:
259: /////////////////////////////////////////////////////////////////////////////
260: // Selection support
261:
262: void CMainWnd::SetSelection(CItemWnd* pNewSelection)
263: {
264: if (pNewSelection != GetTopWindow() && pNewSelection != NULL)
265: pNewSelection->BringWindowToTop();
266:
267: if (m_pSelection != pNewSelection)
268: {
269: // de-select old
270: if (m_pSelection != NULL)
271: m_pSelection->Select(FALSE);
272: // select the new
273: if (pNewSelection != NULL)
274: {
275: pNewSelection->Select(TRUE);
276: }
277: m_pSelection = pNewSelection;
278: }
279: }
280:
281: void CMainWnd::OnActivate(UINT nState, CWnd*, BOOL)
282: {
283: if (m_pSelection)
284: m_pSelection->Select(nState != 0);
285: }
286:
287: /////////////////////////////////////////////////////////////////////////////
288:
289: void CMainWnd::OnCut()
290: {
291: if (!DoCopySelection())
292: {
293: ErrorMessage(E_CLIPBOARD_CUT_FAILED);
294: return;
295: }
296: // cut it out
297: OnClear();
298: Dirty();
299: }
300:
301:
302: void CMainWnd::OnCopy()
303: {
304: if (!DoCopySelection())
305: ErrorMessage(E_CLIPBOARD_COPY_FAILED);
306: }
307:
308: BOOL CMainWnd::DoCopySelection()
309: {
310: CItemWnd* pSel = GetSelection();
311: ASSERT(pSel != NULL);
312:
313: if (!OpenClipboard())
314: return FALSE;
315:
316: /* Empty the clipboard */
317: EmptyClipboard();
318:
319: TRY
320: pSel->GetEmbedded()->CopyToClipboard();
321: CATCH (CException, e)
322: return FALSE;
323: END_CATCH
324:
325: CloseClipboard();
326: return TRUE;
327: }
328:
329:
330: void CMainWnd::OnClear()
331: {
332: ASSERT(GetSelection() != NULL);
333: CItemWnd* pSel = GetSelection();
334:
335: if (pSel)
336: pSel->DestroyWindow();
337:
338: Dirty();
339: }
340:
341: void CMainWnd::ClearAll()
342: {
343: CWnd* pKid;
344: while ((pKid = GetTopWindow()) != NULL)
345: {
346: VERIFY(pKid->DestroyWindow());
347: }
348: }
349:
350: void CMainWnd::OnClearAll()
351: {
352: ClearAll(); /* Wipes out all items */
353: Dirty();
354: }
355:
356: void CMainWnd::OnPaste()
357: {
358: if (!DoPaste(FALSE))
359: ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
360: Dirty();
361: }
362:
363: void CMainWnd::OnPasteLink()
364: {
365: if (!DoPaste(TRUE))
366: ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
367: }
368:
369: BOOL CMainWnd::DoPaste(BOOL fLink)
370: {
371: if (!OpenClipboard())
372: return NULL; /* Couldn't open the clipboard */
373:
374: Hourglass(TRUE);
375:
376: /* Don't replace the current object unless we're successful */
377: CItemWnd* pItemWnd = new CItemWnd(this);
378: CEmbeddedItem* pItem = pItemWnd->GetEmbedded();
379: char szName[OLE_MAXNAMESIZE];
380: CreateNewUniqueName(szName);
381:
382: TRY
383: {
384: if (fLink)
385: {
386: if (!pItem->CreateLinkFromClipboard(szName))
387: AfxThrowMemoryException(); // any exception will do
388: }
389: else
390: {
391: // paste embedded
392: if (pItem->CreateFromClipboard(szName))
393: {
394: TRACE("embedded an embedded OLE object\n");
395: }
396: else if (pItem->CreateStaticFromClipboard(szName))
397: {
398: TRACE("embedded a static picture object\n");
399: }
400: else
401: {
402: AfxThrowMemoryException(); // any exception will do
403: }
404: }
405: }
406: CATCH (CException, e)
407: {
408: // general cleanup
409: TRACE("failed to embed/link an OLE object\n");
410: delete pItemWnd;
411: pItemWnd = NULL;
412: }
413: END_CATCH
414:
415: CloseClipboard();
416: Hourglass(FALSE);
417:
418: if (pItemWnd == NULL)
419: return FALSE;
420:
421: // create as a live health ItemWnd
422: if (!pItemWnd->CreateItemWindow(TRUE))
423: {
424: delete pItemWnd;
425: return FALSE;
426: }
427:
428: // Success !
429: // (from this point on the PostNcCreate hook will clean up memory)
430: return TRUE;
431: }
432:
433:
434: /////////////////////////////////////////////////////////////////////////////
435: // Insert new object
436:
437: void CMainWnd::OnInsertObject()
438: {
439: CString className;
440:
441: if (!AfxOleInsertDialog(className))
442: return;
443:
444: TRACE("Trying to Insert OLE object (class '%s')\n", (const char*)className);
445: CItemWnd* pItemWnd = new CItemWnd(this);
446: CEmbeddedItem* pItem = pItemWnd->GetEmbedded();
447:
448: char szTmp[OLE_MAXNAMESIZE];
449: TRY
450: {
451: if (!pItem->CreateNewObject(className, CreateNewUniqueName(szTmp)))
452: AfxThrowMemoryException(); // any exception will do
453: }
454: CATCH (CException, e)
455: {
456: ErrorMessage(E_FAILED_TO_CREATE);
457: // clean up item
458: delete pItemWnd;
459: return;
460: }
461: END_CATCH
462:
463: // Create invisible (will become visible later when updated)
464: if (!pItemWnd->CreateItemWindow(FALSE))
465: delete pItemWnd;
466:
467: // Success!
468: // (from this point on the PostNcCreate hook will clean up memory)
469:
470: Dirty();
471: }
472:
473: /////////////////////////////////////////////////////////////////////////////
474:
475: void FixObjectBounds(CRect& rect)
476: {
477: /* If we have an empty rectangle, start at default size */
478: if (rect.IsRectNull())
479: {
480: rect.SetRect(0, 0, CXDEFAULT, CYDEFAULT);
481: }
482: else
483: {
484: // First map from HIMETRIC back to screen coordinates
485: {
486: CClientDC screenDC(NULL);
487:
488: short oldMode = screenDC.SetMapMode(MM_HIMETRIC);
489: screenDC.LPtoDP(&rect);
490: screenDC.SetMapMode(oldMode);
491: }
492:
493: /* Preserve the Aspect Ratio of the picture */
494: DWORD xDiff = (DWORD) (rect.right - rect.left + 1);
495: DWORD yDiff = (DWORD) (rect.bottom - rect.top + 1);
496:
497: /* Don't use *= here because of integer arithmetic. */
498: if (xDiff > CXDEFAULT || yDiff > CYDEFAULT)
499: {
500: if ((xDiff * CYDEFAULT) > (yDiff * CXDEFAULT))
501: {
502: yDiff = ((yDiff * CXDEFAULT) / xDiff);
503: xDiff = CXDEFAULT;
504: }
505: else
506: {
507: xDiff = ((xDiff * CYDEFAULT) / yDiff);
508: yDiff = CYDEFAULT;
509: }
510: }
511: rect.SetRect(0, 0, (int)xDiff - 1, (int)yDiff - 1);
512: }
513: }
514:
515: /////////////////////////////////////////////////////////////////////////////
516: // Name generator helper
517:
518: LPSTR CreateNewUniqueName(LPSTR lpstr)
519: {
520: static int CurrentNumber = 0;
521: wsprintf(lpstr, "%s%04d", (LPSTR)OBJ_NAME_PREFIX, CurrentNumber++);
522: return(lpstr);
523: }
524:
525: /////////////////////////////////////////////////////////////////////////////
526:
527: void CMainWnd::OnEditLinks()
528: {
529: CItemWnd* pSelection = GetSelection();
530:
531: AfxOleLinksDialog(GetDocument());
532: }
533:
534: /////////////////////////////////////////////////////////////////////////////
535: // Diagnostics
536:
537: #ifdef _DEBUG
538: void CMainWnd::AssertValid() const
539: {
540: ASSERT(GetDocument()->IsOpen());
541: }
542: #endif
543:
544: /////////////////////////////////////////////////////////////////////////////
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.