home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap23 / cosmo / figure.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  27.6 KB  |  1,162 lines

  1. /*
  2.  * FIGURE.CPP
  3.  * Cosmo Chapter 23
  4.  *
  5.  * Implementation of the CFigure object for Cosmo.
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13.  
  14.  
  15. #include "cosmo.h"
  16.  
  17.  
  18. /*
  19.  * CFigure::CFigure
  20.  * CFigure::~CFigure
  21.  *
  22.  * Parameters (Constructor):
  23.  *  pfnDestroy      PFNDESTROYED to call when object is destroyed.
  24.  *  pDoc            PCCosmoDoc we're associated with.
  25.  */
  26.  
  27. CFigure::CFigure(PFNDESTROYED pfnDestroy, PCCosmoDoc pDoc)
  28.     {
  29.     m_cRef=0;
  30.     m_pfnDestroy=pfnDestroy;
  31.  
  32.     m_pFR=NULL;     //We get this later through FrameSet.
  33.     m_pDoc=pDoc;
  34.     m_pPL=pDoc->m_pPL;
  35.  
  36.     m_fEmbedded=FALSE;
  37.  
  38.     //NULL any contained interfaces initially.
  39.     m_pImpIPersistStorage=NULL;
  40.     m_pIStorage=NULL;
  41.     m_pIStream=NULL;
  42.     m_pImpIDataObject=NULL;
  43.     m_pIDataAdviseHolder=NULL;
  44.     m_pImpIOleObject=NULL;
  45.     m_pIOleAdviseHolder=NULL;
  46.     m_pIOleClientSite=NULL;
  47.  
  48.     m_clsID=CLSID_CosmoFigure;
  49.     m_cf=pDoc->m_cf;
  50.  
  51.     //These are for IDataObject::QueryGetData
  52.     m_cfeGet=CFORMATETCGET;
  53.  
  54.     SETDefFormatEtc(m_rgfeGet[0], pDoc->m_cf, TYMED_HGLOBAL);
  55.     SETDefFormatEtc(m_rgfeGet[1], pDoc->m_cfEmbedSource
  56.         , TYMED_ISTORAGE);
  57.     SETDefFormatEtc(m_rgfeGet[2], pDoc->m_cfObjectDescriptor
  58.         , TYMED_HGLOBAL);
  59.     SETDefFormatEtc(m_rgfeGet[3], CF_METAFILEPICT, TYMED_MFPICT);
  60.     SETDefFormatEtc(m_rgfeGet[4], CF_BITMAP, TYMED_GDI);
  61.  
  62.     m_pST=NULL;
  63.  
  64.     m_pImpIPersistFile=NULL;
  65.  
  66.     //We live in the document's lifetime, so no need to AddRef here.
  67.     m_pMoniker=m_pDoc->m_pMoniker;
  68.     m_dwRegROT=0L;
  69.  
  70.     //CHAPTER23MOD
  71.     m_pIOleIPSite=NULL;
  72.     m_pIOleIPFrame=NULL;
  73.     m_pIOleIPUIWindow=NULL;
  74.     m_pImpIOleIPObject=NULL;
  75.     m_pImpIOleIPActiveObject=NULL;
  76.     m_hMenuShared=NULL;
  77.     m_hOLEMenu=NULL;
  78.     m_hAccel=NULL;
  79.     m_pHW=NULL;
  80.     m_pTB=NULL;
  81.     m_cyBar=0;
  82.     m_fUndoDeactivates=FALSE;
  83.     m_fAllowInPlace=TRUE;
  84.     m_fForceSave=FALSE;
  85.     //End CHAPTER23MOD
  86.  
  87.     return;
  88.     }
  89.  
  90.  
  91. CFigure::~CFigure(void)
  92.     {
  93.     ReleaseInterface(m_pIOleClientSite);
  94.     ReleaseInterface(m_pIDataAdviseHolder);
  95.     ReleaseInterface(m_pIOleAdviseHolder);
  96.  
  97.     //CHAPTER23MOD
  98.     if (NULL!=m_pHW)
  99.         delete m_pHW;
  100.  
  101.     if (NULL!=m_pST)
  102.         delete m_pST;
  103.  
  104.     /*
  105.      * Free contained interfaces.
  106.      * Container in-place interfaces released during deactivation.
  107.      */
  108.  
  109.     if (NULL!=m_pTB)    //Safety-net
  110.         delete m_pTB;
  111.  
  112.     DeleteInterfaceImp(m_pImpIOleIPObject);
  113.     DeleteInterfaceImp(m_pImpIOleIPActiveObject);
  114.     //End CHAPTER23MOD
  115.  
  116.     //Make sure no one thinks we're still running
  117.     if (0L!=m_dwRegROT)
  118.         INOLE_RevokeAsRunning(&m_dwRegROT);
  119.  
  120.     ReleaseInterface(m_pIStorage)
  121.     ReleaseInterface(m_pIStream)
  122.  
  123.     DeleteInterfaceImp(m_pImpIPersistFile);
  124.     DeleteInterfaceImp(m_pImpIOleObject)
  125.     DeleteInterfaceImp(m_pImpIDataObject)
  126.     DeleteInterfaceImp(m_pImpIPersistStorage);
  127.  
  128.     //Free strings.
  129.     if (NULL!=m_pST)
  130.         delete m_pST;
  131.  
  132.     return;
  133.     }
  134.  
  135.  
  136.  
  137.  
  138.  
  139. /*
  140.  * CFigure::QueryInterface
  141.  * CFigure::AddRef
  142.  * CFigure::Release
  143.  *
  144.  * Purpose:
  145.  *  IUnknown members for CFigure object.
  146.  */
  147.  
  148. STDMETHODIMP CFigure::QueryInterface(REFIID riid, PPVOID ppv)
  149.     {
  150.     *ppv=NULL;
  151.  
  152.     if (IID_IUnknown==riid)
  153.         *ppv=this;
  154.  
  155.     if (IID_IPersist==riid || IID_IPersistStorage==riid)
  156.         *ppv=m_pImpIPersistStorage;
  157.  
  158.     if (IID_IDataObject==riid)
  159.         *ppv=m_pImpIDataObject;
  160.  
  161.     if (IID_IOleObject==riid)
  162.         *ppv=m_pImpIOleObject;
  163.  
  164.     if (IID_IPersistFile==riid)
  165.         *ppv=m_pImpIPersistFile;
  166.  
  167.     //CHAPTER23MOD
  168.     if (IID_IOleWindow==riid || IID_IOleInPlaceObject==riid)
  169.         *ppv=m_pImpIOleIPObject;
  170.     //End CHAPTER23MOD
  171.  
  172.     if (NULL!=*ppv)
  173.         {
  174.         ((LPUNKNOWN)*ppv)->AddRef();
  175.         return NOERROR;
  176.         }
  177.  
  178.     return ResultFromScode(E_NOINTERFACE);
  179.     }
  180.  
  181.  
  182. STDMETHODIMP_(ULONG) CFigure::AddRef(void)
  183.     {
  184.     return ++m_cRef;
  185.     }
  186.  
  187.  
  188. STDMETHODIMP_(ULONG) CFigure::Release(void)
  189.     {
  190.     if (0!=--m_cRef)
  191.         return m_cRef;
  192.  
  193.     if (NULL!=m_pfnDestroy)
  194.         (*m_pfnDestroy)();
  195.  
  196.     //Document deletes us
  197.     return 0;
  198.     }
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205. /*
  206.  * CFigure::Init
  207.  *
  208.  * Purpose:
  209.  *  Performs any initialization of a CFigure that's prone to failure
  210.  *  that we also use internally before exposing the object outside.
  211.  *
  212.  * Parameters:
  213.  *  None
  214.  *
  215.  * Return Value:
  216.  *  BOOL            TRUE if the function is successful,
  217.  *                  FALSE otherwise.
  218.  */
  219.  
  220. BOOL CFigure::Init(void)
  221.     {
  222.     m_pST=new CStringTable(m_pDoc->m_hInst);
  223.  
  224.     if (NULL==m_pST)
  225.         return FALSE;
  226.  
  227.     if (!m_pST->Init(IDS_FIGUREMIN, IDS_FIGUREMAX))
  228.         return FALSE;
  229.  
  230.     //Allocate contained interfaces.
  231.     m_pImpIPersistStorage=new CImpIPersistStorage(this, this);
  232.  
  233.     if (NULL==m_pImpIPersistStorage)
  234.         return FALSE;
  235.  
  236.     m_pImpIDataObject=new CImpIDataObject(this, this);
  237.  
  238.     if (NULL==m_pImpIDataObject)
  239.         return FALSE;
  240.  
  241.     m_pImpIOleObject=new CImpIOleObject(this, this);
  242.  
  243.     if (NULL==m_pImpIOleObject)
  244.         return FALSE;
  245.  
  246.     m_pImpIPersistFile=new CImpIPersistFile(this, this);
  247.  
  248.     if (NULL==m_pImpIPersistFile)
  249.         return FALSE;
  250.  
  251.     //CHAPTER23MOD
  252.     m_pImpIOleIPObject=new CImpIOleInPlaceObject(this, this);
  253.  
  254.     if (NULL==m_pImpIOleIPObject)
  255.         return FALSE;
  256.  
  257.     m_pImpIOleIPActiveObject=new CImpIOleInPlaceActiveObject(this
  258.         , this);
  259.  
  260.     if (NULL==m_pImpIOleIPActiveObject)
  261.         return FALSE;
  262.  
  263.     m_pHW=new CHatchWin(m_pDoc->m_hInst);
  264.  
  265.     if (NULL==m_pHW)
  266.         return FALSE;
  267.  
  268.     //We don't have m_pFR yet from which to get the frame window.
  269.     if (!m_pHW->Init(m_pDoc->Window(), ID_HATCHWINDOW, NULL))
  270.         return FALSE;
  271.     //End CHAPTER23MOD
  272.  
  273.     return TRUE;
  274.     }
  275.  
  276.  
  277.  
  278. /*
  279.  * CFigure::FrameSet
  280.  *
  281.  * Purpose:
  282.  *  Provides the compound document object with access to the frame
  283.  *  of this application for UI purposes.
  284.  *
  285.  * Parameters:
  286.  *  pFR             PCCosmoFrame of the frame window.
  287.  *
  288.  * Return Value:
  289.  *  None
  290.  */
  291.  
  292. void CFigure::FrameSet(PCCosmoFrame pFR)
  293.     {
  294.     m_pFR=pFR;
  295.  
  296.     //CHAPTER23MOD
  297.     //We need this in IOleInPlaceActiveObject::ResizeBorder
  298.     m_cyBar=m_pFR->m_cyBar;
  299.  
  300.     //We need this in IOleInPlaceActiveObject::TranslateAccelerator
  301.     m_hAccel=m_pFR->m_hAccel;
  302.     //End CHAPTER23MOD
  303.     return;
  304.     }
  305.  
  306.  
  307.  
  308.  
  309. /*
  310.  * CFigure::FIsDirty
  311.  *
  312.  * Purpose:
  313.  *  Checks if the document is dirty.  This can be called from
  314.  *  IPersistStorage::IsDirty which doesn't have access to CCosmoDoc.
  315.  *
  316.  * Parameters:
  317.  *  None
  318.  *
  319.  * Return Value:
  320.  *  BOOL            TRUE if dirty, FALSE if clean.
  321.  */
  322.  
  323. BOOL CFigure::FIsDirty(void)
  324.     {
  325.     //CHAPTER23MOD
  326.     //Force a save if we opened after being in-place.
  327.     return m_pDoc->m_fDirty || m_fForceSave;
  328.     //End CHAPTER23MOD
  329.     }
  330.  
  331.  
  332.  
  333.  
  334. /*
  335.  * CFigure::FIsEmbedded
  336.  *
  337.  * Purpose:
  338.  *  Answers if the object is embedded or not.
  339.  *
  340.  * Parameters:
  341.  *  None
  342.  *
  343.  * Return Value:
  344.  *  BOOL            TRUE if the object is embedded, FALSE otherwise.
  345.  */
  346.  
  347. BOOL CFigure::FIsEmbedded(void)
  348.     {
  349.     return m_fEmbedded;
  350.     }
  351.  
  352.  
  353.  
  354.  
  355. /*
  356.  * CFigure::SendAdvise
  357.  *
  358.  * Purpose:
  359.  *  Calls the appropriate IOleClientSite or IAdviseSink member
  360.  *  function for various events such as closure, saving, etc.
  361.  *
  362.  * Parameters:
  363.  *  uCode           UINT OBJECTCODE_* identifying the notification.
  364.  *
  365.  * Return Value:
  366.  *  None
  367.  */
  368.  
  369. void CFigure::SendAdvise(UINT uCode)
  370.     {
  371.     switch (uCode)
  372.         {
  373.         case OBJECTCODE_SAVED:
  374.             if (NULL!=m_pIOleAdviseHolder)
  375.                 m_pIOleAdviseHolder->SendOnSave();
  376.  
  377.             break;
  378.  
  379.         case OBJECTCODE_CLOSED:
  380.             if (NULL!=m_pIOleAdviseHolder)
  381.                 m_pIOleAdviseHolder->SendOnClose();
  382.  
  383.             break;
  384.  
  385.         case OBJECTCODE_RENAMED:
  386.             m_pMoniker=m_pDoc->m_pMoniker;  //For IOleObject::GetMoniker
  387.             m_dwRegROT=m_pDoc->m_dwRegROT;
  388.  
  389.             if (NULL!=m_pIOleAdviseHolder)
  390.                 m_pIOleAdviseHolder->SendOnRename(m_pMoniker);
  391.  
  392.             break;
  393.  
  394.         case OBJECTCODE_SAVEOBJECT:
  395.             if (FIsDirty() && NULL!=m_pIOleClientSite)
  396.                 m_pIOleClientSite->SaveObject();
  397.  
  398.             break;
  399.  
  400.         case OBJECTCODE_DATACHANGED:
  401.             //No flags are necessary here.
  402.             if (NULL!=m_pIDataAdviseHolder)
  403.                 {
  404.                 m_pIDataAdviseHolder->SendOnDataChange
  405.                     (m_pImpIDataObject, 0, 0);
  406.                 }
  407.  
  408.             //Tell the running object table of the change
  409.             if (0!=m_dwRegROT)
  410.                 INOLE_NoteChangeTime(m_dwRegROT, NULL, NULL);
  411.  
  412.             //CHAPTER23MOD
  413.             /*
  414.              * If this is the first change after activation, tell the
  415.              * container to free any undo information it's holding.
  416.              */
  417.             if (NULL!=m_pIOleIPSite && m_fUndoDeactivates)
  418.                 m_pIOleIPSite->DiscardUndoState();
  419.  
  420.             m_fUndoDeactivates=FALSE;
  421.             //End CHAPTER23MOD
  422.  
  423.             break;
  424.  
  425.         case OBJECTCODE_SHOWWINDOW:
  426.             if (NULL!=m_pIOleClientSite)
  427.                 m_pIOleClientSite->OnShowWindow(TRUE);
  428.  
  429.             break;
  430.  
  431.         case OBJECTCODE_HIDEWINDOW:
  432.             if (NULL!=m_pIOleClientSite)
  433.                 m_pIOleClientSite->OnShowWindow(FALSE);
  434.  
  435.             break;
  436.  
  437.         case OBJECTCODE_SHOWOBJECT:
  438.             if (NULL!=m_pIOleClientSite)
  439.                 m_pIOleClientSite->ShowObject();
  440.  
  441.             break;
  442.         }
  443.  
  444.     return;
  445.     }
  446.  
  447.  
  448.  
  449.  
  450. //CHAPTER23MOD
  451. /*
  452.  * CFigure::InPlaceActivate
  453.  *
  454.  * Purpose:
  455.  *  Goes through all the steps of activating the Figure as an
  456.  *  in-place object.
  457.  *
  458.  * Parameters:
  459.  *  pActiveSite     LPOLECLIENTSITE of the active site we show in.
  460.  *  fIncludeUI      BOOL indicating if we should do UI as well.
  461.  *
  462.  * Return Value:
  463.  *  HRESULT         Whatever error code is appropriate.
  464.  */
  465.  
  466. HRESULT CFigure::InPlaceActivate(LPOLECLIENTSITE pActiveSite
  467.     , BOOL fIncludeUI)
  468.     {
  469.     HRESULT                 hr;
  470.     HWND                    hWnd, hWndHW;
  471.     RECT                    rcPos;
  472.     RECT                    rcClip;
  473.  
  474.     if (NULL==pActiveSite)
  475.         return ResultFromScode(E_INVALIDARG);
  476.  
  477.     //If we're already active, do the UI and we're done.
  478.     if (NULL!=m_pIOleIPSite)
  479.         {
  480.         if (fIncludeUI)
  481.             UIActivate();
  482.  
  483.         return NOERROR;
  484.         }
  485.  
  486.     /*
  487.      * 1.  Initialization, obtaining interfaces, calling
  488.      *     OnInPlaceActivate.
  489.      */
  490.     hr=pActiveSite->QueryInterface(IID_IOleInPlaceSite
  491.         , (PPVOID)&m_pIOleIPSite);
  492.  
  493.     if (FAILED(hr))
  494.         return hr;
  495.  
  496.     hr=m_pIOleIPSite->CanInPlaceActivate();
  497.  
  498.     if (NOERROR!=hr)
  499.         {
  500.         m_pIOleIPSite->Release();
  501.         m_pIOleIPSite=NULL;
  502.         return ResultFromScode(E_FAIL);
  503.         }
  504.  
  505.     m_pIOleIPSite->OnInPlaceActivate();
  506.     m_fUndoDeactivates=TRUE;
  507.  
  508.     /*
  509.      * 2.  Get the window context and create a window or change the
  510.      *     parent and position of an existing window.  Servers are
  511.      *     required to full cb in the OLEINPLACEFRAMEINFO structure.
  512.      */
  513.     m_pIOleIPSite->GetWindow(&hWnd);
  514.     m_pFR->m_frameInfo.cb=sizeof(OLEINPLACEFRAMEINFO);
  515.  
  516.     m_pIOleIPSite->GetWindowContext(&m_pIOleIPFrame
  517.         , &m_pIOleIPUIWindow, &rcPos, &rcClip
  518.         , &m_pFR->m_frameInfo);
  519.  
  520.     /*
  521.      * Copy container frame pointer to CCosmoFrame for accelerators.
  522.      * No AddRef because frame never messes with it.  Note also that
  523.      * we don't do anything special with our own accelerators here
  524.      * because we just use the same ones as always.
  525.      */
  526.     m_pFR->m_pIOleIPFrame=m_pIOleIPFrame;
  527.  
  528.     /*
  529.      * We'll use a hatch window as the child of the container and the
  530.      * editing window as a child of the hatch window.  We already
  531.      * created the hatch window, so now all we have to do is put it
  532.      * in the right place and stick the Polyline in it.
  533.      */
  534.  
  535.     m_pHW->HwndAssociateSet(m_pFR->Window());
  536.  
  537.     m_pHW->ChildSet(m_pPL->Window());   //Calls SetParent
  538.     m_pHW->RectsSet(&rcPos, &rcClip);   //Positions polyline
  539.  
  540.     hWndHW=m_pHW->Window();
  541.     SetParent(hWndHW, hWnd);            //Move the hatch window
  542.     ShowWindow(hWndHW, SW_SHOW);        //Make us visible.
  543.     SendAdvise(OBJECTCODE_SHOWOBJECT);
  544.  
  545.     if (fIncludeUI)
  546.         return UIActivate();
  547.  
  548.     return NOERROR;
  549.     }
  550.  
  551.  
  552.  
  553.  
  554. /*
  555.  * CFigure::InPlaceDeactivate
  556.  *
  557.  * Purpose:
  558.  *  Reverses all the activation steps from InPlaceActivate.
  559.  *
  560.  * Parameters:
  561.  *  None
  562.  *
  563.  * Return Value:
  564.  *  None
  565.  */
  566.  
  567. void CFigure::InPlaceDeactivate(void)
  568.     {
  569.     RECT        rc;
  570.  
  571.     UIDeactivate();
  572.  
  573.     /*
  574.      * When setting the parent back to the normal document,
  575.      * reposition the Polyline to be at (8,8) instead of at wherever
  576.      * it was in the container's window or our hatch window.  This
  577.      * is so if we are deactivating to open in our own window the
  578.      * Polyline appears in the proper place in the document window.
  579.      */
  580.  
  581.     SetParent(m_pPL->Window(), m_pDoc->m_hWnd);
  582.     m_pHW->ChildSet(NULL);
  583.  
  584.     //Make sure the hatch window is invisible and owned by Cosmo
  585.     ShowWindow(m_pHW->Window(), SW_HIDE);
  586.     SetParent(m_pHW->Window(), m_pDoc->m_hWnd);
  587.  
  588.     GetClientRect(m_pDoc->m_hWnd, &rc);
  589.     InflateRect(&rc, -8, -8);
  590.  
  591.     SetWindowPos(m_pPL->Window(), NULL, rc.left, rc.top
  592.         , rc.right-rc.left, rc.bottom-rc.top
  593.         , SWP_NOZORDER | SWP_NOACTIVATE);
  594.  
  595.     if (NULL!=m_pIOleIPSite)
  596.         m_pIOleIPSite->OnInPlaceDeactivate();
  597.  
  598.     m_pFR->m_pIOleIPFrame=NULL;
  599.     ReleaseInterface(m_pIOleIPFrame);
  600.     ReleaseInterface(m_pIOleIPUIWindow);
  601.     ReleaseInterface(m_pIOleIPSite);
  602.  
  603.     return;
  604.     }
  605.  
  606.  
  607.  
  608. /*
  609.  * CFigure::UIActivate
  610.  *
  611.  * Purpose:
  612.  *  Goes through all the steps of activating the user interface of
  613.  *  the Figure as an in-place object.
  614.  *
  615.  * Parameters:
  616.  *  None
  617.  *
  618.  * Return Value:
  619.  *  HRESULT         NOERROR or error code.
  620.  */
  621.  
  622. HRESULT CFigure::UIActivate(void)
  623.     {
  624.     //1.  Call IOleInPlaceSite::UIActivate
  625.     if (NULL!=m_pIOleIPSite)
  626.         m_pIOleIPSite->OnUIActivate();
  627.  
  628.     //2.  Critical for accelerators to work initially.
  629.     SetFocus(m_pHW->Window());
  630.  
  631.     //3.  Set the active object
  632.  
  633.    #ifdef WIN32ANSI
  634.     OLECHAR     szTemp[40];
  635.  
  636.     MultiByteToWideChar(CP_ACP, 0, PSZ(IDS_INPLACETITLE)
  637.         , -1, szTemp, 40);
  638.    #endif
  639.  
  640.     if (NULL!=m_pIOleIPFrame)
  641.         {
  642.         m_pIOleIPFrame->SetActiveObject(m_pImpIOleIPActiveObject
  643.            #ifdef WIN32ANSI
  644.             , szTemp);
  645.            #else
  646.             , PSZ(IDS_INPLACETITLE));
  647.            #endif
  648.         }
  649.  
  650.     if (NULL!=m_pIOleIPUIWindow)
  651.         {
  652.         m_pIOleIPUIWindow->SetActiveObject(m_pImpIOleIPActiveObject
  653.            #ifdef WIN32ANSI
  654.             , szTemp);
  655.            #else
  656.             , PSZ(IDS_INPLACETITLE));
  657.            #endif
  658.         }
  659.  
  660.     //4.  Create frame tools
  661.     InPlaceToolsCreate();
  662.  
  663.     //5.  Create the shared menu.
  664.     InPlaceMenuCreate();
  665.  
  666.     return NOERROR;
  667.     }
  668.  
  669.  
  670.  
  671.  
  672.  
  673. /*
  674.  * CFigure::UIDeactivate
  675.  *
  676.  * Purpose:
  677.  *  Reverses all the user interface activation steps from
  678.  *  UIActivate.
  679.  *
  680.  * Parameters:
  681.  *  None
  682.  *
  683.  * Return Value:
  684.  *  None
  685.  */
  686.  
  687. void CFigure::UIDeactivate(void)
  688.     {
  689.     //1.  Remove the in-place tools
  690.     InPlaceToolsDestroy();
  691.  
  692.     //2.  Remove the shared menu.
  693.     InPlaceMenuDestroy();
  694.  
  695.     //3.  Set active obejcts to NULL
  696.     if (NULL!=m_pIOleIPFrame)
  697.         m_pIOleIPFrame->SetActiveObject(NULL, NULL);
  698.  
  699.     if (NULL!=m_pIOleIPUIWindow)
  700.         m_pIOleIPUIWindow->SetActiveObject(NULL, NULL);
  701.  
  702.     //3.  Call IOleInPlaceSite::OnUIDeactivate
  703.     if (NULL!=m_pIOleIPSite)
  704.         m_pIOleIPSite->OnUIDeactivate(FALSE);
  705.  
  706.     return;
  707.     }
  708.  
  709.  
  710.  
  711. /*
  712.  * CFigure::InPlaceMenuCreate
  713.  *
  714.  * Purpose:
  715.  *  Creates and sets a menu for an in-place embedded object.
  716.  *
  717.  * Parameters:
  718.  *  None
  719.  *
  720.  * Return Value:
  721.  *  BOOL            TRUE if everything is well, FALSE on error.
  722.  */
  723.  
  724. BOOL CFigure::InPlaceMenuCreate(void)
  725.     {
  726.     HMENU               hMenu, hMenuT;
  727.     UINT                uTemp=MF_BYPOSITION | MF_POPUP;
  728.     UINT                i;
  729.     OLEMENUGROUPWIDTHS  mgw;
  730.  
  731.     for (i=0; i<6; i++)
  732.         mgw.width[i]=0;
  733.  
  734.     //We already have popup menu handles in m_pFR->m_phMenu[]
  735.  
  736.     //Create the new shared menu and let container do its thing
  737.     hMenu=CreateMenu();
  738.     m_pIOleIPFrame->InsertMenus(hMenu, &mgw);
  739.  
  740.     /*
  741.      * Add our menus remembering that the container has added its
  742.      * already.
  743.      */
  744.     InsertMenu(hMenu, (UINT)mgw.width[0]
  745.        , uTemp, (UINT)m_pFR->m_phMenu[1], PSZ(IDS_MENUEDIT));
  746.  
  747.     /*
  748.      * Add the Open item to the edit menu.
  749.      * NOTE:  If you are a multiple-use server, this sort of code
  750.      * will also modify the menu on the server window as well as
  751.      * this shared menu in which case you need a separate popup menu
  752.      * altogether.
  753.      */
  754.     AppendMenu(m_pFR->m_phMenu[1], MF_SEPARATOR, 0, NULL);
  755.     AppendMenu(m_pFR->m_phMenu[1], MF_STRING, IDM_EDITOPEN
  756.         , PSZ(IDS_MENUOPEN));
  757.  
  758.     InsertMenu(hMenu, (UINT)mgw.width[0]+1+(UINT)mgw.width[2]
  759.        , uTemp, (UINT)m_pFR->m_phMenu[2], PSZ(IDS_MENUCOLOR));
  760.  
  761.     InsertMenu(hMenu, (UINT)mgw.width[0]+1+(UINT)mgw.width[2]+1
  762.        , uTemp, (UINT)m_pFR->m_phMenu[3], PSZ(IDS_MENULINE));
  763.  
  764.     //Window menu position changes between MDI and SDI
  765.    #ifdef MDI
  766.     hMenuT=m_pFR->m_phMenu[5];
  767.    #else
  768.     hMenuT=m_pFR->m_phMenu[4];
  769.    #endif
  770.  
  771.     InsertMenu(hMenu, (UINT)mgw.width[0]+1+(UINT)mgw.width[2]+2
  772.         + (UINT)mgw.width[4], uTemp, (UINT)hMenuT
  773.         , PSZ(IDS_MENUHELP));
  774.  
  775.     //Tell OLE how many items in each group are ours.
  776.     mgw.width[1]=1;
  777.     mgw.width[3]=2;
  778.     mgw.width[5]=1;
  779.  
  780.     m_hMenuShared=hMenu;
  781.     m_hOLEMenu=OleCreateMenuDescriptor(m_hMenuShared, &mgw);
  782.  
  783.     m_pIOleIPFrame->SetMenu(m_hMenuShared, m_hOLEMenu
  784.         , m_pFR->Window());
  785.     return TRUE;
  786.     }
  787.  
  788.  
  789.  
  790.  
  791. /*
  792.  * CFigure::InPlaceMenuDestroy
  793.  *
  794.  * Purpose:
  795.  *  Performs opposite actions from InPlaceMenuCreate
  796.  *
  797.  * Parameters:
  798.  *  None
  799.  *
  800.  * Return Value:
  801.  *  BOOL            TRUE if all is well, FALSE otherwise.
  802.  */
  803.  
  804. BOOL CFigure::InPlaceMenuDestroy(void)
  805.     {
  806.     int         cItems, i, j;
  807.     HMENU       hMenuT;
  808.  
  809.     //If we don't have a shared menu, nothing to do.
  810.     if (NULL==m_hMenuShared)
  811.         return TRUE;
  812.  
  813.     //Stop the container frame from using this menu.
  814.     m_pIOleIPFrame->SetMenu(NULL, NULL, NULL);
  815.  
  816.     //Clean up what we got from OleCreateMenuDescriptor.
  817.     OleDestroyMenuDescriptor(m_hOLEMenu);
  818.     m_hOLEMenu=NULL;
  819.  
  820.     cItems=GetMenuItemCount(m_hMenuShared);
  821.  
  822.     /*
  823.      * Walk backwards down the menu.  For each popup, see if it
  824.      * matches any other popup we know about, and if so, remove
  825.      * it from the shared menu.
  826.      */
  827.     for (i=cItems; i >=0; i--)
  828.         {
  829.         hMenuT=GetSubMenu(m_hMenuShared, i);
  830.  
  831.         for (j=0; j <= CMENUS; j++)
  832.             {
  833.             /*
  834.              * If the submenu matches any we have, remove, don't
  835.              * delete. Since we're walking backwards this only
  836.              * affects the positions of those menus after us so the
  837.              * GetSubMenu call above is not affected.
  838.              */
  839.             if (hMenuT==m_pFR->m_phMenu[j])
  840.                 RemoveMenu(m_hMenuShared, i, MF_BYPOSITION);
  841.             }
  842.         }
  843.  
  844.     /*
  845.      * Remove the Open item and separator from the Edit menu.
  846.      * NOTE:  If you are a multiple-user server, this affects the
  847.      * menu on the server window as well as the shared menu in which
  848.      * case you need to use a separate popup menu altogether.
  849.      */
  850.     RemoveMenu(m_pFR->m_phMenu[1], MPOS_OPEN, MF_BYPOSITION);
  851.     RemoveMenu(m_pFR->m_phMenu[1], MPOS_SEP,  MF_BYPOSITION);
  852.  
  853.     if (NULL!=m_pIOleIPFrame)
  854.         m_pIOleIPFrame->RemoveMenus(m_hMenuShared);
  855.  
  856.     DestroyMenu(m_hMenuShared);
  857.     m_hMenuShared=NULL;
  858.     return TRUE;
  859.     }
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866. /*
  867.  * CFigure::InPlaceToolsCreate
  868.  *
  869.  * Purpose:
  870.  *  Creates a toolbar for in-place activation and negotiates the
  871.  *  border space for the toolbar.
  872.  *
  873.  * Parameters:
  874.  *  None
  875.  *
  876.  * Return Value:
  877.  *  BOOL            TRUE if we could allocate the space and create
  878.  *                  the tools.  FALSE if we fail, meaning that we
  879.  *                  just do in-place with menus only, since we can
  880.  *                  do without the tools.  We could fail and attempt
  881.  *                  to reverse what we might have done already, but
  882.  *                  since we don't really *need* the toolbar, we
  883.  *                  keep going.
  884.  */
  885.  
  886. BOOL CFigure::InPlaceToolsCreate(void)
  887.     {
  888.     BORDERWIDTHS    bw;
  889.     HWND            hWnd;
  890.     UINT            uState=GIZMO_NORMAL;
  891.     UINT            utCmd =GIZMOTYPE_BUTTONCOMMAND;
  892.     UINT            utEx  =GIZMOTYPE_BUTTONATTRIBUTEEX;
  893.     UINT            i;
  894.     HBITMAP         hBmp;
  895.     RECT            rc;
  896.     UINT            dxB, dyB;
  897.  
  898.     //We don't need anything on the document, so send zeros.
  899.     SetRectEmpty((LPRECT)&bw);
  900.  
  901.     if (NULL!=m_pIOleIPUIWindow)
  902.         m_pIOleIPUIWindow->SetBorderSpace(&bw);
  903.  
  904.     if (NULL==m_pIOleIPFrame)
  905.         return FALSE;
  906.  
  907.     /*
  908.      * 1.  Make sure we can reserve space for what we need.  If this
  909.      *     fails then we just do without because the menu has
  910.      *     everything we really need.  A more willing server could
  911.      *     put tools in popup windows as well.
  912.      */
  913.  
  914.     if (!InPlaceToolsRenegotiate())
  915.         {
  916.         //If the container doesn't allow us any, don't ask for any.
  917.         m_pIOleIPFrame->SetBorderSpace(&bw);
  918.         return FALSE;
  919.         }
  920.  
  921.     /*
  922.      * 2.  Create the toolbar window using the container window as
  923.      *     the parent.  In order to get messages from it, we use
  924.      *     it's AssociateSet ability directly after creation and
  925.      *     before we add any tools to the bar.
  926.      */
  927.  
  928.     m_pIOleIPFrame->GetWindow(&hWnd);
  929.  
  930.     //If we already have a toolbar, just show it again.
  931.     if (NULL!=m_pTB)
  932.         {
  933.         ShowWindow(m_pTB->Window(), SW_SHOW);
  934.         return TRUE;
  935.         }
  936.  
  937.     m_pTB=new CToolBar(m_pFR->m_hInst);
  938.  
  939.     if (NULL==m_pTB)
  940.         {
  941.         SetRectEmpty((LPRECT)&bw);
  942.         m_pIOleIPFrame->SetBorderSpace(&bw);
  943.         return FALSE;
  944.         }
  945.  
  946.     m_pTB->Init(hWnd, ID_GIZMOBAR, m_cyBar);
  947.     g_pInPlaceTB=m_pTB;
  948.  
  949.     //Insure the tools are initially invisible
  950.     ShowWindow(m_pTB->Window(), SW_HIDE);
  951.  
  952.     //Tell the toolbar who to send messages to.
  953.     m_pTB->HwndAssociateSet(m_pFR->m_hWnd);
  954.  
  955.     /*
  956.      * Add tools to the bar, setting CFrame::fInit to avoid
  957.      * command processing
  958.      */
  959.     m_pFR->m_fInit=TRUE;
  960.  
  961.     hBmp=m_pFR->m_hBmp;
  962.     dxB=m_pFR->m_dxB;
  963.     dyB=m_pFR->m_dyB;
  964.  
  965.     //Edit Undo, Cut, Copy, Paste
  966.     m_pTB->Add(utCmd, 1, IDM_EDITUNDO,  dxB, dyB, NULL, hBmp, 1, uState);
  967.     m_pTB->Add(utCmd, 2, IDM_EDITCUT,   dxB, dyB, NULL, NULL, 0, uState);
  968.     m_pTB->Add(utCmd, 3, IDM_EDITCOPY,  dxB, dyB, NULL, NULL, 1, uState);
  969.     m_pTB->Add(utCmd, 4, IDM_EDITPASTE, dxB, dyB, NULL, NULL, 2, uState);
  970.  
  971.     //Separator
  972.     m_pTB->Add(GIZMOTYPE_SEPARATOR, 5, 0, 6, dyB, NULL, NULL, 0, uState);
  973.  
  974.     //Color Background and Color Line
  975.     m_pTB->Add(utCmd, 6, IDM_COLORBACKGROUND, dxB, dyB, NULL, hBmp, 3
  976.                , GIZMO_NORMAL | PRESERVE_BLACK);
  977.  
  978.     m_pTB->Add(utCmd, 7, IDM_COLORLINE, dxB, dyB, NULL, hBmp, 4, uState);
  979.  
  980.     //Separator
  981.     m_pTB->Add(GIZMOTYPE_SEPARATOR, 8, 0, 6, dyB, NULL, NULL, 0, uState);
  982.  
  983.     //Line styles.
  984.     m_pTB->Add(utEx, 19, IDM_LINESOLID, dxB, dyB, NULL, hBmp, 5, uState);
  985.     m_pTB->Add(utEx, 10, IDM_LINEDASH, dxB, dyB, NULL, hBmp, 6, uState);
  986.     m_pTB->Add(utEx, 11, IDM_LINEDOT, dxB, dyB, NULL, hBmp, 7, uState);
  987.     m_pTB->Add(utEx, 12, IDM_LINEDASHDOT, dxB, dyB, NULL, hBmp, 8
  988.         , uState);
  989.     m_pTB->Add(utEx, 13, IDM_LINEDASHDOTDOT, dxB, dyB, NULL, hBmp, 9
  990.         , uState);
  991.  
  992.     //Check the current line style.
  993.     i=m_pPL->LineStyleGet()+IDM_LINEMIN;
  994.     m_pTB->Check(i, TRUE);
  995.  
  996.     m_pFR->m_fInit=FALSE;
  997.  
  998.     /*
  999.      * Before making the toolbar visible, resize it to the
  1000.      * container's GetBorder rectangle.  By default the toolbar
  1001.      * sizes itself to the client area of the parent, but we can't
  1002.      * assume that's the same as GetBorder returns, so we do the
  1003.      * extra work here.
  1004.      */
  1005.  
  1006.     m_pIOleIPFrame->GetBorder(&rc);
  1007.     SetWindowPos(m_pTB->Window(), NULL, rc.left, rc.top
  1008.         , rc.right-rc.left, rc.top+m_cyBar, SWP_NOZORDER);
  1009.  
  1010.  
  1011.     //3.  Make the tools visible.
  1012.     ShowWindow(m_pTB->Window(), SW_SHOW);
  1013.  
  1014.     return TRUE;
  1015.     }
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022. /*
  1023.  * CFigure::InPlaceToolsDestroy
  1024.  *
  1025.  * Purpose:
  1026.  *  Reverses the process of InPlaceToolsCreate
  1027.  *
  1028.  * Parameters:
  1029.  *  None
  1030.  *
  1031.  * Return Value:
  1032.  *  BOOL            TRUE if successful, FALSE otherwise.
  1033.  */
  1034.  
  1035.  
  1036. BOOL CFigure::InPlaceToolsDestroy(void)
  1037.     {
  1038.     //Nothing to do if we never created anything.
  1039.     if (NULL==m_pTB)
  1040.         return TRUE;
  1041.  
  1042.     /*
  1043.      * No reason to call SetBorderSpace with an empty rectangle
  1044.      * since you call IOleInPlaceSite::OnUIDeactivate.  The
  1045.      * container will restore its own tools appropriately.
  1046.      */
  1047.  
  1048.     //Destroy the toolbar.
  1049.     if (NULL!=m_pTB)
  1050.         {
  1051.         delete m_pTB;
  1052.         m_pTB=NULL;
  1053.         g_pInPlaceTB=NULL;
  1054.         }
  1055.  
  1056.     return TRUE;
  1057.     }
  1058.  
  1059.  
  1060.  
  1061. /*
  1062.  * CFigure::InPlaceToolsRenegotiate
  1063.  *
  1064.  * Purpose:
  1065.  *  Calls IOleInPlaceFrame::RequestBorderSpace and SetBorderSpace
  1066.  *  to reserve space for our toolbar.
  1067.  *
  1068.  * Parameters:
  1069.  *  None
  1070.  *
  1071.  * Return Value:
  1072.  *  BOOL            TRUE if all is well, FALSE otherwise.
  1073.  */
  1074.  
  1075. BOOL CFigure::InPlaceToolsRenegotiate(void)
  1076.     {
  1077.     HRESULT         hr;
  1078.     BORDERWIDTHS    bw;
  1079.  
  1080.     SetRect((LPRECT)&bw, 0, m_pFR->m_cyBar, 0, 0);
  1081.  
  1082.     hr=m_pIOleIPFrame->RequestBorderSpace(&bw);
  1083.  
  1084.     if (NOERROR!=hr)
  1085.         return FALSE;
  1086.  
  1087.     //Safety net:  RequestBorderSpace may modify values in bw
  1088.     SetRect((LPRECT)&bw, 0, m_pFR->m_cyBar, 0, 0);
  1089.     m_pIOleIPFrame->SetBorderSpace(&bw);
  1090.     return TRUE;
  1091.     }
  1092.  
  1093.  
  1094.  
  1095. /*
  1096.  * CFigure::OpenIntoWindow
  1097.  *
  1098.  * Purpose:
  1099.  *  If we're current open in-place, send ourselves the OPEN verb to
  1100.  *  show into a full window.
  1101.  *
  1102.  * Parameters:
  1103.  *  None
  1104.  *
  1105.  * Return Value:
  1106.  *  None
  1107.  */
  1108.  
  1109. void CFigure::OpenIntoWindow(void)
  1110.     {
  1111.     if (NULL!=m_pIOleIPSite)
  1112.         {
  1113.         //Make sure we don't try to do this.
  1114.         m_fUndoDeactivates=FALSE;
  1115.  
  1116.         /*
  1117.          * We can get away with passing a lot of NULLs since we know
  1118.          * how we implemented DoVerb.
  1119.          */
  1120.         m_pImpIOleObject->DoVerb(OLEIVERB_OPEN, NULL
  1121.             , m_pIOleClientSite, -1, NULL, NULL);
  1122.  
  1123.         //This makes sure we save ourselves when closing.
  1124.         m_fForceSave=TRUE;
  1125.  
  1126.         //Repaint the container immediately
  1127.         SendAdvise(OBJECTCODE_DATACHANGED);
  1128.         }
  1129.  
  1130.     return;
  1131.     }
  1132.  
  1133.  
  1134.  
  1135. /*
  1136.  * Undo
  1137.  *
  1138.  * Purpose:
  1139.  *  If we have not done anything else in this object then call
  1140.  *  IOleInPlaceSite::DeactivateAndUndo and return TRUE, otherwise
  1141.  *  just return FALSE.  Note that the m_fUndoDeactivates is set
  1142.  *  to FALSE in CFigure::SendAdvise for OBJECTCODE_DATACHANGED.
  1143.  *
  1144.  * Parameters:
  1145.  *  None
  1146.  *
  1147.  * Return Value:
  1148.  *  BOOL            TRUE if we deactivated, FALSE otherwise.
  1149.  */
  1150.  
  1151. BOOL CFigure::Undo(void)
  1152.     {
  1153.     if (!m_fUndoDeactivates)
  1154.         return FALSE;
  1155.  
  1156.     m_fUndoDeactivates=FALSE;
  1157.     m_pIOleIPSite->DeactivateAndUndo();
  1158.     return TRUE;
  1159.     }
  1160.  
  1161. //End CHAPTER23MOD
  1162.