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 / ioleobj.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  20.5 KB  |  877 lines

  1. /*
  2.  * IOLEOBJ.CPP
  3.  * Cosmo Chapter 23
  4.  *
  5.  * Implementation of the IOleObject interface for Polyline.
  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.  * CImpIOleObject::CImpIOleObject
  20.  * CImpIOleObject::~CImpIOleObject
  21.  *
  22.  * Parameters (Constructor):
  23.  *  pObj            PCFigure of the object we're in.
  24.  *  pUnkOuter       LPUNKNOWN to which we delegate.
  25.  */
  26.  
  27. CImpIOleObject::CImpIOleObject(PCFigure pObj, LPUNKNOWN pUnkOuter)
  28.     {
  29.     m_cRef=0;
  30.     m_pObj=pObj;
  31.     m_pUnkOuter=pUnkOuter;
  32.     return;
  33.     }
  34.  
  35. CImpIOleObject::~CImpIOleObject(void)
  36.     {
  37.     return;
  38.     }
  39.  
  40.  
  41.  
  42. /*
  43.  * CImpIOleObject::QueryInterface
  44.  * CImpIOleObject::AddRef
  45.  * CImpIOleObject::Release
  46.  */
  47.  
  48. STDMETHODIMP CImpIOleObject::QueryInterface(REFIID riid, PPVOID ppv)
  49.     {
  50.     return m_pUnkOuter->QueryInterface(riid, ppv);
  51.     }
  52.  
  53. STDMETHODIMP_(ULONG) CImpIOleObject::AddRef(void)
  54.     {
  55.     ++m_cRef;
  56.     return m_pUnkOuter->AddRef();
  57.     }
  58.  
  59. STDMETHODIMP_(ULONG) CImpIOleObject::Release(void)
  60.     {
  61.     --m_cRef;
  62.     return m_pUnkOuter->Release();
  63.     }
  64.  
  65.  
  66.  
  67.  
  68.  
  69. /*
  70.  * CImpIOleObject::SetClientSite
  71.  *
  72.  * Purpose:
  73.  *  Provides the object with a pointer to the IOleClient site
  74.  *  representing the container in which this object resides.
  75.  *
  76.  * Parameters:
  77.  *  pIOleClientSite LPOLECLIENTSITE to the container's interface.
  78.  *
  79.  * Return Value:
  80.  *  HRESULT         NOERROR
  81.  */
  82.  
  83. STDMETHODIMP CImpIOleObject::SetClientSite
  84.     (LPOLECLIENTSITE pIOleClientSite)
  85.     {
  86.     if (NULL!=m_pObj->m_pIOleClientSite)
  87.         m_pObj->m_pIOleClientSite->Release();
  88.  
  89.     m_pObj->m_pIOleClientSite=pIOleClientSite;
  90.     m_pObj->m_pIOleClientSite->AddRef();
  91.     return NOERROR;
  92.     }
  93.  
  94.  
  95.  
  96.  
  97.  
  98. /*
  99.  * CImpIOleObject::GetClientSite
  100.  *
  101.  * Purpose:
  102.  *  Asks the object for the client site provided in SetClientSite.
  103.  *  If you have not seen SetClientSite yet, return a NULL in
  104.  *  ppIOleClientSite.
  105.  *
  106.  * Parameters:
  107.  *  ppSite          LPOLECLIENTSITE * in which to store the
  108.  *                  pointer.
  109.  *
  110.  * Return Value:
  111.  *  HRESULT         NOERROR
  112.  */
  113.  
  114. STDMETHODIMP CImpIOleObject::GetClientSite(LPOLECLIENTSITE
  115.     *ppSite)
  116.     {
  117.     //Be sure to AddRef the new pointer you are giving away.
  118.     *ppSite=m_pObj->m_pIOleClientSite;
  119.     m_pObj->m_pIOleClientSite->AddRef();
  120.  
  121.     return NOERROR;
  122.     }
  123.  
  124.  
  125.  
  126.  
  127.  
  128. /*
  129.  * CImpIOleObject::SetHostNames
  130.  *
  131.  * Purpose:
  132.  *  Provides the object with names of the container application and
  133.  *  the object in the container to use in object user interface.
  134.  *
  135.  * Parameters:
  136.  *  pszApp          LPCOLESTR of the container application.
  137.  *  pszObj          LPCOLESTR of some name useful in window titles.
  138.  *
  139.  * Return Value:
  140.  *  HRESULT         NOERROR
  141.  */
  142.  
  143. STDMETHODIMP CImpIOleObject::SetHostNames(LPCOLESTR pszApp
  144.     , LPCOLESTR pszObj)
  145.     {
  146.     m_pObj->m_fEmbedded=TRUE;
  147.    #ifdef WIN32ANSI
  148.     char        szApp[80], szObj[80];
  149.  
  150.     szApp[0]=0;
  151.     szObj[0]=0;
  152.  
  153.     if (NULL!=pszApp)
  154.         {
  155.         WideCharToMultiByte(CP_ACP, 0, pszApp, -1, szApp, 80
  156.             , NULL, NULL);
  157.         }
  158.  
  159.     if (NULL!=pszObj)
  160.         {
  161.         WideCharToMultiByte(CP_ACP, 0, pszObj, -1, szObj, 80
  162.             , NULL, NULL);
  163.         }
  164.  
  165.     m_pObj->m_pFR->UpdateEmbeddingUI(TRUE, m_pObj->m_pDoc
  166.         , szApp, szObj);
  167.    #else
  168.     m_pObj->m_pFR->UpdateEmbeddingUI(TRUE, m_pObj->m_pDoc
  169.         , pszApp, pszObj);
  170.    #endif
  171.     return NOERROR;
  172.     }
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179. /*
  180.  * CImpIOleObject::Close
  181.  *
  182.  * Purpose:
  183.  *  Forces the object to close down its user interface and unload.
  184.  *
  185.  * Parameters:
  186.  *  dwSaveOption    DWORD describing the circumstances under which
  187.  *                  the object is being saved and closed.
  188.  *
  189.  * Return Value:
  190.  *  HRESULT         NOERROR or a general error value.
  191.  */
  192.  
  193. STDMETHODIMP CImpIOleObject::Close(DWORD dwSaveOption)
  194.     {
  195.     HWND        hWnd;
  196.     BOOL        fSave=FALSE;
  197.  
  198.     hWnd=m_pObj->m_pDoc->Window();
  199.  
  200.     //If object is dirty and we're asked to save, save it and close.
  201.     if (OLECLOSE_SAVEIFDIRTY==dwSaveOption && m_pObj->FIsDirty())
  202.         fSave=TRUE;
  203.  
  204.     /*
  205.      * If asked to prompt, only do so if dirty, then if we get a
  206.      * YES, save as usual and close.  On NO, just close.  On
  207.      * CANCEL return OLE_E_PROMPTSAVECANCELLED.
  208.      */
  209.     if (OLECLOSE_PROMPTSAVE==dwSaveOption && m_pObj->FIsDirty())
  210.         {
  211.         UINT        uRet;
  212.  
  213.         uRet=MessageBox(hWnd, (*m_pObj->m_pST)[IDS_CLOSECAPTION]
  214.             , (*m_pObj->m_pST)[IDS_CLOSEPROMPT], MB_YESNOCANCEL);
  215.  
  216.         if (IDCANCEL==uRet)
  217.             return ResultFromScode(OLE_E_PROMPTSAVECANCELLED);
  218.  
  219.         if (IDYES==uRet)
  220.             fSave=TRUE;
  221.         }
  222.  
  223.     if (fSave)
  224.         {
  225.         m_pObj->SendAdvise(OBJECTCODE_SAVEOBJECT);
  226.         m_pObj->SendAdvise(OBJECTCODE_SAVED);
  227.         }
  228.  
  229.     //We get directly here on OLECLOSE_NOSAVE.
  230.     PostMessage(hWnd, WM_CLOSE, 0, 0L);
  231.     return NOERROR;
  232.     }
  233.  
  234.  
  235.  
  236.  
  237.  
  238. /*
  239.  * CImpIOleObject::SetMoniker
  240.  *
  241.  * Purpose:
  242.  *  Informs the object of its moniker or its container's moniker
  243.  *  depending on dwWhich.
  244.  *
  245.  * Parameters:
  246.  *  dwWhich         DWORD describing whether the moniker is the
  247.  *                  object's or the container's.
  248.  *  pmk             LPMONIKER with the name.
  249.  *
  250.  * Return Value:
  251.  *  HRESULT         NOERROR or a general error value.
  252.  */
  253.  
  254. STDMETHODIMP CImpIOleObject::SetMoniker(DWORD dwWhich
  255.     , LPMONIKER pmk)
  256.     {
  257.     LPMONIKER       pmkFull;
  258.     HRESULT         hr=ResultFromScode(E_FAIL);
  259.  
  260.     /*
  261.      * For an embedded object we might be living in a container that
  262.      * has given us away as a link.  This is our indication to
  263.      * register the full moniker for this object that we obtain from
  264.      * IOleClientSite::GetMoniker(OLEWHICHMK_FULL).
  265.      */
  266.  
  267.     if (NULL!=m_pObj->m_pIOleClientSite)
  268.         {
  269.         hr=m_pObj->m_pIOleClientSite->GetMoniker
  270.             (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
  271.             , &pmkFull);
  272.         }
  273.  
  274.     if (SUCCEEDED(hr))
  275.         {
  276.         /*
  277.          * If this moniker is already running then we don't
  278.          * need to revoke and re-register the same thing again.
  279.          */
  280.         if (NOERROR==pmkFull->IsRunning(NULL, NULL, NULL))
  281.             {
  282.             pmkFull->Release();
  283.             return NOERROR;
  284.             }
  285.  
  286.         //This will revoke the old one if m_dwRegROT is nonzero.
  287.         INOLE_RegisterAsRunning(m_pObj, pmkFull
  288.             , 0, &m_pObj->m_dwRegROT);
  289.  
  290.         //Inform clients of the new moniker
  291.         if (NULL!=m_pObj->m_pIOleAdviseHolder)
  292.             m_pObj->m_pIOleAdviseHolder->SendOnRename(pmkFull);
  293.  
  294.         pmkFull->Release();
  295.         }
  296.  
  297.     return hr;
  298.     }
  299.  
  300.  
  301.  
  302.  
  303.  
  304. /*
  305.  * CImpIOleObject::GetMoniker
  306.  *
  307.  * Purpose:
  308.  *  Asks the object for a moniker that can later be used to
  309.  *  reconnect to it.
  310.  *
  311.  * Parameters:
  312.  *  dwAssign        DWORD determining how to assign the moniker to
  313.  *                  to the object.
  314.  *  dwWhich         DWORD describing which moniker the caller wants.
  315.  *  ppmk            LPMONIKER * into which to store the moniker.
  316.  *
  317.  * Return Value:
  318.  *  HRESULT         NOERROR or a general error value.
  319.  */
  320.  
  321. STDMETHODIMP CImpIOleObject::GetMoniker(DWORD dwAssign
  322.     , DWORD dwWhich, LPMONIKER * ppmk)
  323.     {
  324.     HRESULT         hr=ResultFromScode(E_FAIL);
  325.  
  326.     *ppmk=NULL;
  327.  
  328.     /*
  329.      * When we support linking we either return our file moniker if
  330.      * we're linked, or out full moniker from the container if we're
  331.      * embedded.
  332.      */
  333.  
  334.     if (NULL!=m_pObj->m_pMoniker)
  335.         {
  336.         *ppmk=m_pObj->m_pMoniker;       //Document file moniker
  337.         m_pObj->m_pMoniker->AddRef();
  338.         }
  339.     else
  340.         {
  341.         //Get the full container:object moniker if we're embedded
  342.         if (NULL!=m_pObj->m_pIOleClientSite)
  343.             {
  344.             hr=m_pObj->m_pIOleClientSite->GetMoniker
  345.                 (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
  346.                 , ppmk);
  347.             }
  348.         }
  349.  
  350.     return (NULL!=*ppmk) ? NOERROR : hr;
  351.     }
  352.  
  353.  
  354.  
  355.  
  356.  
  357. /*
  358.  * CImpIOleObject::InitFromData
  359.  *
  360.  * Purpose:
  361.  *  Initializes the object from the contents of a data object.
  362.  *
  363.  * Parameters:
  364.  *  pIDataObject    LPDATAOBJECT containing the data.
  365.  *  fCreation       BOOL indicating if this is part of a new
  366.  *                  creation. If FALSE, the container is trying
  367.  *                  to paste here.
  368.  *  dwReserved      DWORD reserved.
  369.  *
  370.  * Return Value:
  371.  *  HRESULT         NOERROR or a general error value.
  372.  */
  373.  
  374. STDMETHODIMP CImpIOleObject::InitFromData(LPDATAOBJECT pIDataObject
  375.     , BOOL fCreation, DWORD dwReserved)
  376.     {
  377.     BOOL    fRet;
  378.  
  379.     /*
  380.      * If we get a data object here, try to paste from it.  If
  381.      * you've written clipboard code already, this is a snap.
  382.      * We don't really care about fCreation or not since pasting
  383.      * in us blasts away whatever is already here.
  384.      */
  385.     fRet=m_pObj->m_pDoc->PasteFromData(pIDataObject);
  386.     return fRet ? NOERROR : ResultFromScode(E_FAIL);
  387.     }
  388.  
  389.  
  390.  
  391.  
  392.  
  393. /*
  394.  * CImpIOleObject::GetClipboardData
  395.  *
  396.  * Purpose:
  397.  *  Returns an IDataObject pointer to the caller representing what
  398.  *  would be on the clipboard if the server did an Edit/Copy using
  399.  *  OleSetClipboard.
  400.  *
  401.  * Parameters:
  402.  *  dwReserved      DWORD reserved.
  403.  *  ppIDataObj      LPDATAOBJECT * into which to store the
  404.  *                  pointer.
  405.  *
  406.  * Return Value:
  407.  *  HRESULT         NOERROR or a general error value.
  408.  */
  409.  
  410. STDMETHODIMP CImpIOleObject::GetClipboardData(DWORD dwReserved
  411.     , LPDATAOBJECT *ppIDataObj)
  412.     {
  413.     /*
  414.      * Again, if you have a function to create a data object for the
  415.      * clipboard, this is a simple implementation.  The one we have
  416.      * does all the compound document formats already.
  417.      */
  418.     *ppIDataObj=m_pObj->m_pDoc->TransferObjectCreate(FALSE);
  419.     return (NULL!=*ppIDataObj) ? NOERROR : ResultFromScode(E_FAIL);
  420.     }
  421.  
  422.  
  423.  
  424.  
  425.  
  426. /*
  427.  * CImpIOleObject::DoVerb
  428.  *
  429.  * Purpose:
  430.  *  Executes an object-defined action.
  431.  *
  432.  * Parameters:
  433.  *  iVerb           LONG index of the verb to execute.
  434.  *  pMSG            LPMSG describing the event causing the
  435.  *                  activation.
  436.  *  pActiveSite     LPOLECLIENTSITE to the site involved.
  437.  *  lIndex          LONG the piece on which execution is happening.
  438.  *  hWndParent      HWND of window in which the object can play
  439.  *                  in-place.
  440.  *  pRectPos        LPRECT of the object in hWndParent where the
  441.  *                  object can play in-place if desired.
  442.  *
  443.  * Return Value:
  444.  *  HRESULT         NOERROR or a general error value.
  445.  */
  446.  
  447. STDMETHODIMP CImpIOleObject::DoVerb(LONG iVerb, LPMSG pMSG
  448.     , LPOLECLIENTSITE pActiveSite, LONG lIndex, HWND hWndParent
  449.     , LPCRECT pRectPos)
  450.     {
  451.     HWND            hWnd, hWndT;
  452.  
  453.     //CHAPTER23MOD
  454.     /*
  455.      * Find the upper most window.  Note that for in-place activation
  456.      * we must start at the document to find our uppermost frame because
  457.      * the object editing window may be a child of the container now.
  458.      */
  459.     //End CHAPTER23MOD
  460.     hWndT=GetParent(m_pObj->m_pDoc->Window());
  461.  
  462.     while (NULL!=hWndT)
  463.         {
  464.         hWnd=hWndT;
  465.         hWndT=GetParent(hWndT);
  466.         }
  467.  
  468.     switch (iVerb)
  469.         {
  470.         //CHAPTER23MOD
  471.         case OLEIVERB_HIDE:
  472.             if (NULL!=m_pObj->m_pIOleIPSite)
  473.                 m_pObj->InPlaceDeactivate();
  474.             else
  475.                 {
  476.                 ShowWindow(hWnd, SW_HIDE);
  477.                 m_pObj->SendAdvise(OBJECTCODE_HIDEWINDOW);
  478.                 }
  479.             break;
  480.  
  481.         case OLEIVERB_PRIMARY:
  482.         case OLEIVERB_SHOW:
  483.             //If already IP active, nothing much to do here.
  484.             if (NULL!=m_pObj->m_pIOleIPSite)
  485.                 return NOERROR;
  486.  
  487.             if (m_pObj->m_fAllowInPlace)
  488.                 {
  489.                 if (SUCCEEDED(m_pObj->InPlaceActivate(pActiveSite
  490.                     , TRUE)))
  491.                     {
  492.                     return NOERROR;
  493.                     }
  494.                 }
  495.  
  496.             //FALL-THROUGH
  497.  
  498.         case OLEIVERB_OPEN:
  499.             /*
  500.              * If we're already in-place active, deactivate and
  501.              * prevent later reactivation.
  502.              */
  503.             if (NULL!=m_pObj->m_pIOleIPSite)
  504.                 {
  505.                 m_pObj->InPlaceDeactivate();
  506.                 m_pObj->m_fAllowInPlace=FALSE;
  507.                 }
  508.  
  509.             /*
  510.              * With all the in-place stuff gone, we can go back to
  511.              * our normal open state.
  512.              */
  513.  
  514.             ShowWindow(hWnd, SW_SHOW);
  515.             SetForegroundWindow(hWnd);
  516.             SetFocus(hWnd);
  517.  
  518.             m_pObj->SendAdvise(OBJECTCODE_SHOWOBJECT);
  519.             m_pObj->SendAdvise(OBJECTCODE_SHOWWINDOW);
  520.             break;
  521.  
  522.         case OLEIVERB_INPLACEACTIVATE:
  523.             //This means activate in-place but no UI.
  524.             return m_pObj->InPlaceActivate(pActiveSite, FALSE);
  525.  
  526.         case OLEIVERB_UIACTIVATE:
  527.             //This means fully activate in-place with full UI
  528.             return m_pObj->InPlaceActivate(pActiveSite, TRUE);
  529.  
  530.         case OLEIVERB_DISCARDUNDOSTATE:
  531.             //We don't hold a state, but if you do, free it here.
  532.             break;
  533.         //End CHAPTER23MOD
  534.  
  535.         default:
  536.             return ResultFromScode(OLEOBJ_S_INVALIDVERB);
  537.         }
  538.  
  539.     return NOERROR;
  540.     }
  541.  
  542.  
  543.  
  544.  
  545.  
  546. /*
  547.  * CImpIOleObject::EnumVerbs
  548.  *
  549.  * Purpose:
  550.  *  Creates an enumerator that knows the object's verbs.  If you
  551.  *  need to change the verb list dynamically, then you'll need to
  552.  *  implement this, otherwise you can return OLE_S_USEREG.
  553.  *
  554.  * Parameters:
  555.  *  ppEnum          LPENUMOLEVERB * into which to return the
  556.  *                  enum.
  557.  *
  558.  * Return Value:
  559.  *  HRESULT         NOERROR or a general error value.
  560.  */
  561.  
  562. STDMETHODIMP CImpIOleObject::EnumVerbs(LPENUMOLEVERB *ppEnum)
  563.     {
  564.     //Trivial implementation if you fill the regDB.
  565.     return ResultFromScode(OLE_S_USEREG);
  566.     }
  567.  
  568.  
  569.  
  570.  
  571.  
  572. /*
  573.  * CImpIOleObject::Update
  574.  *
  575.  * Purpose:
  576.  *  Insures that the object is up to date.  This is mostly used for
  577.  *  caching but you must make sure that you recursively call all
  578.  *  nested objects you contain as well.
  579.  *
  580.  * Parameters:
  581.  *  None
  582.  *
  583.  * Return Value:
  584.  *  HRESULT         NOERROR or a general error value.
  585.  */
  586.  
  587. STDMETHODIMP CImpIOleObject::Update(void)
  588.     {
  589.     //We're always updated since we don't contain.
  590.     return NOERROR;
  591.     }
  592.  
  593.  
  594.  
  595.  
  596.  
  597. /*
  598.  * CImpIOleObject::IsUpToDate
  599.  *
  600.  * Purpose:
  601.  *  Returns if the object is currently up to date, which involves
  602.  *  asking all contained object inside this object if they are up
  603.  *  to date as well.
  604.  *
  605.  * Parameters:
  606.  *  None
  607.  *
  608.  * Return Value:
  609.  *  HRESULT         NOERROR if successful, S_FALSE if dirty.
  610.  */
  611.  
  612. STDMETHODIMP CImpIOleObject::IsUpToDate(void)
  613.     {
  614.     //We're always updated since we don't contain.
  615.     return NOERROR;
  616.     }
  617.  
  618.  
  619.  
  620.  
  621.  
  622. /*
  623.  * CImpIOleObject::GetUserClassID
  624.  *
  625.  * Purpose:
  626.  *  Used for linked objects, this returns the class ID of what end
  627.  *  users think they are editing.
  628.  *
  629.  * Parameters:
  630.  *  pClsID          LPCLSID in which to store the CLSID.
  631.  *
  632.  * Return Value:
  633.  *  HRESULT         NOERROR or a general error value.
  634.  */
  635.  
  636. STDMETHODIMP CImpIOleObject::GetUserClassID(LPCLSID pClsID)
  637.     {
  638.     /*
  639.      * If you are not registered to handle data other than yourself,
  640.      * then you can just return your class ID here.  If you are
  641.      * registered as usable from Treat-As dialogs, then you need
  642.      * to return the CLSID of what you are really editing.
  643.      */
  644.  
  645.     *pClsID=m_pObj->m_clsID;
  646.     return NOERROR;
  647.     }
  648.  
  649.  
  650.  
  651.  
  652.  
  653. /*
  654.  * CImpIOleObject::GetUserType
  655.  *
  656.  * Purpose:
  657.  *  Determines the user-presentable name of the object.
  658.  *
  659.  * Parameters:
  660.  *  dwForm          DWORD describing which form of the string is
  661.  *                  desired.
  662.  *  pszType         LPOLESTR * into which to return the pointer to
  663.  *                  the type string.
  664.  *
  665.  * Return Value:
  666.  *  HRESULT         NOERROR or a general error value.
  667.  */
  668.  
  669. STDMETHODIMP CImpIOleObject::GetUserType(DWORD dwForm
  670.     , LPOLESTR *ppszType)
  671.     {
  672.     return ResultFromScode(OLE_S_USEREG);
  673.     }
  674.  
  675.  
  676.  
  677.  
  678.  
  679. /*
  680.  * CImpIOleObject::SetExtent
  681.  *
  682.  * Purpose:
  683.  *  Sets the size of the object in HIMETRIC units.
  684.  *
  685.  * Parameters:
  686.  *  dwAspect        DWORD of the aspect affected.
  687.  *  pszl            LPSIZEL containing the new size.
  688.  *
  689.  * Return Value:
  690.  *  HRESULT         NOERROR or a general error value.
  691.  */
  692.  
  693. STDMETHODIMP CImpIOleObject::SetExtent(DWORD dwAspect, LPSIZEL pszl)
  694.     {
  695.     RECT            rc;
  696.     SIZEL           szl;
  697.  
  698.     if (!(DVASPECT_CONTENT & dwAspect))
  699.         return ResultFromScode(E_FAIL);
  700.  
  701.     XformSizeInHimetricToPixels(NULL, pszl, &szl);
  702.  
  703.     //This resizes the window to match the container's size.
  704.     SetRect(&rc, 0, 0, (int)szl.cx, (int)szl.cy);
  705.     m_pObj->m_pPL->SizeSet(&rc, TRUE);
  706.  
  707.     return NOERROR;
  708.     }
  709.  
  710.  
  711.  
  712.  
  713.  
  714. /*
  715.  * CImpIOleObject::GetExtent
  716.  *
  717.  * Purpose:
  718.  *  Retrieves the size of the object in HIMETRIC units.
  719.  *
  720.  * Parameters:
  721.  *  dwAspect        DWORD of the aspect requested
  722.  *  pszl            LPSIZEL into which to store the size.
  723.  *
  724.  * Return Value:
  725.  *  HRESULT         NOERROR or a general error value.
  726.  */
  727.  
  728. STDMETHODIMP CImpIOleObject::GetExtent(DWORD dwAspect, LPSIZEL pszl)
  729.     {
  730.     RECT            rc;
  731.     SIZEL           szl;
  732.  
  733.     if (!(DVASPECT_CONTENT & dwAspect))
  734.         return ResultFromScode(E_FAIL);
  735.  
  736.     m_pObj->m_pPL->RectGet(&rc);
  737.     szl.cx=rc.right-rc.left;
  738.     szl.cy=rc.bottom-rc.top;
  739.  
  740.     XformSizeInPixelsToHimetric(NULL, &szl, pszl);
  741.     return NOERROR;
  742.     }
  743.  
  744.  
  745.  
  746.  
  747.  
  748. /*
  749.  * CImpIOleObject::Advise
  750.  *
  751.  * Purpose:
  752.  *  Provides an IAdviseSink to the object for notifications.
  753.  *
  754.  * Parameters:
  755.  *  pIAdviseSink    LPADVISESINK to notify.
  756.  *  pdwConn         LPDWORD into which to store a connection key.
  757.  *
  758.  * Return Value:
  759.  *  HRESULT         NOERROR or a general error value.
  760.  */
  761.  
  762. STDMETHODIMP CImpIOleObject::Advise(LPADVISESINK pIAdviseSink
  763.     , LPDWORD pdwConn)
  764.     {
  765.     if (NULL==m_pObj->m_pIOleAdviseHolder)
  766.         {
  767.         HRESULT     hr;
  768.  
  769.         hr=CreateOleAdviseHolder(&m_pObj->m_pIOleAdviseHolder);
  770.  
  771.         if (FAILED(hr))
  772.             return hr;
  773.         }
  774.  
  775.     return m_pObj->m_pIOleAdviseHolder->Advise(pIAdviseSink
  776.         , pdwConn);
  777.     }
  778.  
  779.  
  780.  
  781.  
  782.  
  783. /*
  784.  * CImpIOleObject::Unadvise
  785.  *
  786.  * Purpose:
  787.  *  Terminates a previous advise connection from Advise.
  788.  *
  789.  * Parameters:
  790.  *  dwConn          DWORD connection key from Advise.
  791.  *
  792.  * Return Value:
  793.  *  HRESULT         NOERROR or a general error value.
  794.  */
  795.  
  796. STDMETHODIMP CImpIOleObject::Unadvise(DWORD dwConn)
  797.     {
  798.     if (NULL!=m_pObj->m_pIOleAdviseHolder)
  799.         return m_pObj->m_pIOleAdviseHolder->Unadvise(dwConn);
  800.  
  801.     return ResultFromScode(E_FAIL);
  802.     }
  803.  
  804.  
  805.  
  806.  
  807.  
  808. /*
  809.  * CImpIOleObject::EnumAdvise
  810.  *
  811.  * Purpose:
  812.  *  Creates and returns a enumeration of the advises on this object.
  813.  *
  814.  * Parameters:
  815.  *  ppEnum          LPENUMSTATDATA * in which to return the
  816.  *                  enumerator.
  817.  *
  818.  * Return Value:
  819.  *  HRESULT         NOERROR or a general error value.
  820.  */
  821.  
  822. STDMETHODIMP CImpIOleObject::EnumAdvise(LPENUMSTATDATA *ppEnum)
  823.     {
  824.     if (NULL!=m_pObj->m_pIOleAdviseHolder)
  825.         return m_pObj->m_pIOleAdviseHolder->EnumAdvise(ppEnum);
  826.  
  827.     return ResultFromScode(E_FAIL);
  828.     }
  829.  
  830.  
  831.  
  832.  
  833.  
  834. /*
  835.  * CImpIOleObject::GetMiscStatus
  836.  *
  837.  * Purpose:
  838.  *  Returns a set of miscellaneous status flags for the object.
  839.  *
  840.  * Parameters:
  841.  *  dwAspect        DWORD of the aspect in question.
  842.  *  pdwStatus       LPDWORD in which to store the flags.
  843.  *
  844.  * Return Value:
  845.  *  HRESULT         NOERROR or a general error value.
  846.  */
  847.  
  848. STDMETHODIMP CImpIOleObject::GetMiscStatus(DWORD dwAspect
  849.     , LPDWORD pdwStatus)
  850.     {
  851.     return ResultFromScode(OLE_S_USEREG);
  852.     }
  853.  
  854.  
  855.  
  856.  
  857.  
  858. /*
  859.  * CImpIOleObject::SetColorScheme
  860.  *
  861.  * Purpose:
  862.  *  Provides the object with the color palette as recommended by
  863.  *  the container application that also knows the palettes of other
  864.  *  objects.  The object here is not required to use these colors.
  865.  *
  866.  * Parameters:
  867.  *  pLP             LPLOGPALETTE providing the colors.
  868.  *
  869.  * Return Value:
  870.  *  HRESULT         NOERROR or a general error value.
  871.  */
  872.  
  873. STDMETHODIMP CImpIOleObject::SetColorScheme(LPLOGPALETTE pLP)
  874.     {
  875.     return ResultFromScode(E_NOTIMPL);
  876.     }
  877.