home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / C++-7 / DISK8 / MFC / SAMPLES / OCLIENT / MAINWND.CP$ / mainwnd
Encoding:
Text File  |  1992-03-16  |  12.4 KB  |  545 lines

  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. /////////////////////////////////////////////////////////////////////////////
  545.