TENANT.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:23k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * TENANT.CPP
  3.  * Patron Chapter 13
  4.  *
  5.  * Implementation of the CTentant class which holds information
  6.  * for a single object on a page.  It maintains position, references
  7.  * to data, and a storage.
  8.  *
  9.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Microsoft
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15. #include "patron.h"
  16. /*
  17.  * CTenant::CTenant
  18.  * CTenant::~CTenant
  19.  *
  20.  * Constructor Parameters:
  21.  *  dwID            DWORD identifier for this page.
  22.  *  hWnd            HWND of the pages window.
  23.  *  pPG             PCPages to the parent structure.
  24.  */
  25. CTenant::CTenant(DWORD dwID, HWND hWnd, PCPages pPG)
  26.     {
  27.     m_hWnd=hWnd;
  28.     m_dwID=dwID;
  29.     m_fInitialized=0;
  30.     m_pIStorage=NULL;
  31.     m_cOpens=0;
  32.     m_pObj=NULL;
  33.     m_pPG =pPG;
  34.     m_clsID=CLSID_NULL;
  35.     m_fSetExtent=FALSE;
  36.     return;
  37.     }
  38. CTenant::~CTenant(void)
  39.     {
  40.     if (NULL!=m_pObj)
  41.         {
  42.         //We know we only hold one reference from Create or Load
  43.         m_pObj->Release();
  44.         m_pObj=NULL;
  45.         }
  46.     return;
  47.     }
  48. /*
  49.  * CTenant::GetID
  50.  *
  51.  * Return Value:
  52.  *  DWORD           dwID field in this tenant.
  53.  */
  54. DWORD CTenant::GetID(void)
  55.     {
  56.     return m_dwID;
  57.     }
  58. /*
  59.  * CTenant::GetStorageName
  60.  *
  61.  * Parameters:
  62.  *  pszName         LPOLESTR to a buffer in which to store the storage
  63.  *                  name for this tenant.
  64.  *
  65.  * Return Value:
  66.  *  UINT            Number of characters stored.
  67.  */
  68. UINT CTenant::GetStorageName(LPOLESTR pszName)
  69.     {
  70.    #ifdef WIN32ANSI
  71.     char        szTemp[32];
  72.     UINT        cch;
  73.     cch=wsprintf(szTemp, "Tenant %lu", m_dwID);
  74.     MultiByteToWideChar(CP_ACP, 0, szTemp, -1, pszName, 32);
  75.     return cch;
  76.    #else
  77.     return wsprintf(pszName, TEXT("Tenant %lu"), m_dwID);
  78.    #endif
  79.     }
  80. /*
  81.  * CTenant::Create
  82.  *
  83.  * Purpose:
  84.  *  Creates a new tenant of the given CLSID, which can be either a
  85.  *  static bitmap or metafile now (Chapter 13) and which may
  86.  *  eventually be any compound document object.
  87.  *
  88.  * Parameters:
  89.  *  tType           TENANTTYPE to create, either a static metafile,
  90.  *                  bitmap, or some kind of compound document object
  91.  *                  This determines which OleCreate* call we use.
  92.  *  pvType          LPVOID providing the relevant pointer from which
  93.  *                  to create the tenant, depending on iType.
  94.  *  pFE             LPFORMATETC specifying the type of renderings
  95.  *                  to use.
  96.  *  pptl            PPOINTL in which we store offset coordinates.
  97.  *  pszl            LPSIZEL where this object should store its
  98.  *                  lometric extents.
  99.  *  pIStorage       LPSTORAGE of the page we live in.  We have to
  100.  *                  create another storage in this for the tenant.
  101.  *  ppo             PPATRONOBJECT containing placement data.
  102.  *  dwData          DWORD with extra data, sensitive to iType.
  103.  *
  104.  * Return Value:
  105.  *  UINT            A CREATE_* value depending on what we
  106.  *                  actually do.
  107.  */
  108. UINT CTenant::Create(TENANTTYPE tType, LPVOID pvType
  109.     , LPFORMATETC pFE, PPOINTL pptl, LPSIZEL pszl
  110.     , LPSTORAGE pIStorage, PPATRONOBJECT ppo, DWORD dwData)
  111.     {
  112.     HRESULT         hr;
  113.     LPUNKNOWN       pObj;
  114.     LPVIEWOBJECT2   pIViewObject2;
  115.     LPOLEOBJECT     pIOleObject;
  116.     UINT            uRet=CREATE_GRAPHICONLY;
  117.     if (NULL==pvType || NULL==pIStorage)
  118.         return CREATE_FAILED;
  119.     //Fail if this is called for an already living tenant.
  120.     if (m_fInitialized)
  121.         return CREATE_FAILED;
  122.     m_fInitialized=TRUE;
  123.     //Create a new storage for this tenant.
  124.     if (!Open(pIStorage))
  125.         return CREATE_FAILED;
  126.     /*
  127.      * Get the placement info if it's here.  We either have a non-
  128.      * NULL PPATRONOBJECT in ppo or we have to use default
  129.      * placement and retrieve the size from the object itself.
  130.      */
  131.     pszl->cx=0;
  132.     pszl->cy=0;
  133.     if (NULL!=ppo)
  134.         {
  135.         *pFE=ppo->fe;
  136.         *pptl=ppo->ptl;
  137.         *pszl=ppo->szl;     //Could be 0,0 , so we ask object
  138.         uRet=CREATE_PLACEDOBJECT;
  139.         }
  140.     hr=ResultFromScode(E_FAIL);
  141.     //Now create an object based specifically for the type.
  142.     switch (tType)
  143.         {
  144.         case TENANTTYPE_NULL:
  145.             break;
  146.         case TENANTTYPE_STATIC:
  147.             /*
  148.              * We could use OleCreateStaticFromData here which does
  149.              * pretty much what we're doing below.  However, it does
  150.              * not allow us to control whether we paste a bitmap or
  151.              * a metafile--it uses metafile first, bitmap second.
  152.              * For this reason we'll use code developed in Chapter
  153.              * 11's FreeLoader to affect the paste.
  154.              */
  155.             hr=CreateStatic((LPDATAOBJECT)pvType, pFE, &pObj);
  156.             break;
  157.         default:
  158.             break;
  159.         }
  160.     //If creation didn't work, get rid of the element Open created.
  161.     if (FAILED(hr))
  162.         {
  163.         Destroy(pIStorage);
  164.         return CREATE_FAILED;
  165.         }
  166.     //Otherwise, store the object pointer and initialize the tenant
  167.     m_pObj=pObj;
  168.     m_fe=*pFE;
  169.     m_fe.ptd=NULL;
  170.     m_dwState=TENANTSTATE_DEFAULT;
  171.     //If we also saw PatronObjects on the clipboard, we have size
  172.     if (0==pszl->cx && 0==pszl->cy)
  173.         {
  174.         SIZEL   szl;
  175.         //Try to get the real size of the object, default to 2"*2"
  176.         SETSIZEL((*pszl), 2*LOMETRIC_PER_INCH, 2*LOMETRIC_PER_INCH);
  177.         //Try IViewObject2 first, then IOleObject as a backup.
  178.         hr=pObj->QueryInterface(IID_IViewObject2
  179.             , (PPVOID)&pIViewObject2);
  180.         if (SUCCEEDED(hr))
  181.             {
  182.             pIViewObject2->GetExtent(m_fe.dwAspect, -1, NULL, &szl);
  183.             pIViewObject2->Release();
  184.             }
  185.         else
  186.             {
  187.             hr=pObj->QueryInterface(IID_IOleObject
  188.                 , (PPVOID)&pIOleObject);
  189.             if (SUCCEEDED(hr))
  190.                 {
  191.                 pIOleObject->GetExtent(m_fe.dwAspect, &szl);
  192.                 pIOleObject->Release();
  193.                 }
  194.             }
  195.         if (SUCCEEDED(hr))
  196.             {
  197.             //Convert HIMETRIC to our LOMETRIC mapping
  198.             SETSIZEL((*pszl), szl.cx/10, szl.cy/10);
  199.             }
  200.         }
  201.     return uRet;
  202.     }
  203. /*
  204.  * CTenant::Load
  205.  *
  206.  * Purpose:
  207.  *  Recreates the object living in this tenant in place of calling
  208.  *  FCreate.  This is used in loading as opposed to new creation.
  209.  *
  210.  * Parameters:
  211.  *  pIStorage       LPSTORAGE of the page we live in.
  212.  *  pti             PTENTANTINFO containing persistent information.
  213.  *                  The ID value in this structure is ignored.
  214.  *
  215.  * Return Value:
  216.  *  BOOL            TRUE if successful, FALSE otherwise.
  217.  */
  218. BOOL CTenant::Load(LPSTORAGE pIStorage, PTENANTINFO pti)
  219.     {
  220.     HRESULT         hr;
  221.     LPUNKNOWN       pObj;
  222.     if (NULL==pIStorage || NULL==pti)
  223.         return FALSE;
  224.     //Fail if this is called for an already living tenant.
  225.     if (m_fInitialized)
  226.         return FALSE;
  227.     m_fInitialized=TRUE;
  228.     //Open the storage for this tenant.
  229.     if (!Open(pIStorage))
  230.         return FALSE;
  231.     hr=OleLoad(m_pIStorage, IID_IUnknown, NULL, (PPVOID)&pObj);
  232.     if (FAILED(hr))
  233.         {
  234.         Destroy(pIStorage);
  235.         return FALSE;
  236.         }
  237.     //Otherwise, store the object pointer and initialize the tenant
  238.     m_pObj=pObj;
  239.     m_fe=pti->fe;
  240.     m_fe.ptd=NULL;
  241.     m_fSetExtent=pti->fSetExtent;
  242.     m_dwState=TENANTSTATE_DEFAULT;
  243.     RectSet(&pti->rcl, FALSE);
  244.     return TRUE;
  245.     }
  246. /*
  247.  * CTenant::GetInfo
  248.  *
  249.  * Purpose:
  250.  *  Retrieved a TENANTINFO structure for this tenant.
  251.  *
  252.  * Parameters:
  253.  *  pti             PTENANTINFO structure to fill
  254.  *
  255.  * Return Value:
  256.  *  None
  257.  */
  258. void CTenant::GetInfo(PTENANTINFO pti)
  259.     {
  260.     if (NULL!=pti)
  261.         {
  262.         pti->dwID=m_dwID;
  263.         pti->rcl=m_rcl;
  264.         pti->fe=m_fe;
  265.         pti->fSetExtent=m_fSetExtent;
  266.         }
  267.     return;
  268.     }
  269. /*
  270.  * CTenant::Open
  271.  *
  272.  * Purpose:
  273.  *  Retrieves the IStorage associated with this tenant.  The
  274.  *  IStorage is owned by the tenant and thus the tenant always
  275.  *  holds a reference count.
  276.  *
  277.  *  If the storage is already open for this tenant, then this
  278.  *  function will AddRef it; therefore the caller must always
  279.  *  match an Open with a Close.
  280.  *
  281.  * Parameters:
  282.  *  pIStorage       LPSTORAGE above this tenant (which has its
  283.  *                  own storage).
  284.  *
  285.  * Return Value:
  286.  *  BOOL            TRUE if opening succeeds, FALSE otherwise.
  287.  */
  288. BOOL CTenant::Open(LPSTORAGE pIStorage)
  289.     {
  290.     HRESULT     hr=NOERROR;
  291.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE
  292.                     | STGM_SHARE_EXCLUSIVE;
  293.     OLECHAR     szTemp[32];
  294.     if (NULL==m_pIStorage)
  295.         {
  296.         if (NULL==pIStorage)
  297.             return FALSE;
  298.         /*
  299.          * Attempt to open the storage under this ID.  If there is
  300.          * none, then create it.  In either case we end up with an
  301.          * IStorage that we either save in pPage or release.
  302.          */
  303.         GetStorageName(szTemp);
  304.         hr=pIStorage->OpenStorage(szTemp, NULL, dwMode, NULL, 0
  305.             , &m_pIStorage);
  306.         if (FAILED(hr))
  307.             {
  308.             hr=pIStorage->CreateStorage(szTemp, dwMode, 0, 0
  309.                 , &m_pIStorage);
  310.             }
  311.         }
  312.     else
  313.         m_pIStorage->AddRef();
  314.     if (FAILED(hr))
  315.         return FALSE;
  316.     m_cOpens++;
  317.     return TRUE;
  318.     }
  319. /*
  320.  * CTenant::Close
  321.  *
  322.  * Purpose:
  323.  *  Possibly commits the storage, then releases it reversing the
  324.  *  reference count from Open.  If the reference on the storage
  325.  *  goes to zero, the storage is forgotten.  However, the object we
  326.  *  contain is still held and as long as it's active the storage
  327.  *  remains alive.
  328.  *
  329.  * Parameters:
  330.  *  fCommit         BOOL indicating if we're to commit.
  331.  *
  332.  * Return Value:
  333.  *  None
  334.  */
  335. void CTenant::Close(BOOL fCommit)
  336.     {
  337.     if (fCommit)
  338.         Update();
  339.     if (NULL!=m_pIStorage)
  340.         {
  341.         m_pIStorage->Release();
  342.         /*
  343.          * We can't use a zero reference count to know when to NULL
  344.          * this since other things might have AddRef'd the storage.
  345.          */
  346.         if (0==--m_cOpens)
  347.             m_pIStorage=NULL;
  348.         }
  349.     return;
  350.     }
  351. /*
  352.  * CTenant::Update
  353.  *
  354.  * Purpose:
  355.  *  Forces a common on the page if it's open.
  356.  *
  357.  * Parameters:
  358.  *  None
  359.  *
  360.  * Return Value:
  361.  *  BOOL            TRUE if the object is open, FALSE otherwise.
  362.  */
  363. BOOL CTenant::Update(void)
  364.     {
  365.     LPPERSISTSTORAGE    pIPS;
  366.     if (NULL!=m_pIStorage)
  367.         {
  368.         /*
  369.          * We need to OleSave again because we might have changed
  370.          * the size or position of this tenant.  We also need to
  371.          * save the rectangle on the page, since that's not known
  372.          * to OLE.
  373.          */
  374.         m_pObj->QueryInterface(IID_IPersistStorage, (PPVOID)&pIPS);
  375.         if (FAILED(OleSave(pIPS, m_pIStorage, TRUE)))
  376.             {
  377.             //This is essentially what OleSave does.
  378.             WriteClassStg(m_pIStorage, m_clsID);
  379.             pIPS->Save(m_pIStorage, TRUE);
  380.             }
  381.         pIPS->SaveCompleted(NULL);
  382.         pIPS->Release();
  383.         m_pIStorage->Commit(STGC_ONLYIFCURRENT);
  384.         }
  385.     return FALSE;
  386.     }
  387. /*
  388.  * CTenant::Destroy
  389.  *
  390.  * Purpose:
  391.  *  Removes this page from the given storage.  The caller should
  392.  *  eventually delete this CTenant object to free the object herein.
  393.  *  Nothing is committed when being destroyed.
  394.  *
  395.  * Parameters:
  396.  *  pIStorage       LPSTORAGE contianing this page on which to call
  397.  *                  DestroyElement
  398.  *
  399.  * Return Value:
  400.  *  None
  401.  */
  402. void CTenant::Destroy(LPSTORAGE pIStorage)
  403.     {
  404.     OLECHAR     szTemp[32];
  405.     if (NULL!=pIStorage)
  406.         {
  407.         if (NULL!=m_pIStorage)
  408.             {
  409.             //Remove all reference/open counts on this storage.
  410.             while (0!=m_cOpens)
  411.                 {
  412.                 m_pIStorage->Release();
  413.                 m_cOpens--;
  414.                 }
  415.             }
  416.         GetStorageName(szTemp);
  417.         pIStorage->DestroyElement(szTemp);
  418.         m_pIStorage=NULL;
  419.         }
  420.     //m_pObj is released in destructor.
  421.     return;
  422.     }
  423. /*
  424.  * CTenant::Select
  425.  *
  426.  * Purpose:
  427.  *  Selects or deselects the tenant.
  428.  *
  429.  * Parameters:
  430.  *  fSelect         BOOL indicating the new state of the tenant.
  431.  *
  432.  * Return Value:
  433.  *  None
  434.  */
  435. void CTenant::Select(BOOL fSelect)
  436.     {
  437.     BOOL        fWasSelected;
  438.     DWORD       dwState;
  439.     RECT        rc;
  440.     HDC         hDC;
  441.     fWasSelected=(BOOL)(TENANTSTATE_SELECTED & m_dwState);
  442.     //Nothing to do when there's no change.
  443.     if (fWasSelected==fSelect)
  444.         return;
  445.     dwState=m_dwState & ~TENANTSTATE_SELECTED;
  446.     m_dwState=dwState | ((fSelect) ? TENANTSTATE_SELECTED : 0);
  447.     /*
  448.      * Draw sizing handles to show the selection state.  We convert
  449.      * things to MM_TEXT since that's what this function expects.
  450.      */
  451.     RECTFROMRECTL(rc, m_rcl);
  452.     RectConvertMappings(&rc, NULL, TRUE);
  453.     OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
  454.     hDC=GetDC(m_hWnd);
  455.     UIDrawHandles(&rc, hDC, UI_HANDLES_INSIDE
  456.         | UI_HANDLES_NOBORDER | UI_HANDLES_USEINVERSE
  457.         , CXYHANDLE, !fWasSelected);
  458.     ReleaseDC(m_hWnd, hDC);
  459.     if (fSelect)
  460.         m_pPG->m_fDirty=TRUE;
  461.     return;
  462.     }
  463. /*
  464.  * CTenant::Activate
  465.  *
  466.  * Purpose:
  467.  *  Activates a verb on the object living in the tenant.  Does
  468.  *  nothing for static objects.
  469.  *
  470.  * Parameters:
  471.  *  iVerb           LONG of the verb to execute.
  472.  *
  473.  * Return Value:
  474.  *  BOOL            TRUE if the object changed due to this verb
  475.  *                  execution.
  476.  */
  477. BOOL CTenant::Activate(LONG iVerb)
  478.     {
  479.     MessageBeep(0); //Nothing doing for now.
  480.     return FALSE;
  481.     }
  482. /*
  483.  * CTenant::Draw
  484.  *
  485.  * Purpose:
  486.  *  Draws the tenant in its rectangle on the given hDC.  We assume
  487.  *  the DC is already set up for the mapping mode in which our
  488.  *  rectangle is expressed, since the Page we're in tells us both
  489.  *  the rect and the hDC.
  490.  *
  491.  * Parameters:
  492.  *  hDC             HDC in which to draw.  Could be a metafile,
  493.  *                  memory DC, screen, or printer.
  494.  *  ptd             DVTARGETDEVICE * describing the device.
  495.  *  hIC             HDC holding an information context (printing).
  496.  *  xOff, yOff      int offsets for the page in lometric
  497.  *  fNoColor        BOOL indicating if we should do B & W
  498.  *  fPrinter        BOOL indicating if we should render for a
  499.  *                  printer.
  500.  *
  501.  * Return Value:
  502.  *  None
  503.  */
  504. void CTenant::Draw(HDC hDC, DVTARGETDEVICE *ptd, HDC hIC
  505.     , int xOff, int yOff, BOOL fNoColor, BOOL fPrinter)
  506.     {
  507.     HRESULT         hr;
  508.     RECT            rc;
  509.     RECTL           rcl;
  510.     UINT            uMM;
  511.     LPVIEWOBJECT2   pIViewObject2;
  512.     hr=m_pObj->QueryInterface(IID_IViewObject2
  513.         , (PPVOID)&pIViewObject2);
  514.     if (FAILED(hr))
  515.         return;
  516.     RECTFROMRECTL(rc, m_rcl);
  517.     OffsetRect(&rc, -xOff, -yOff);
  518.     RECTLFROMRECT(rcl, rc);
  519.     //We have to use Draw since we have a target device and IC.
  520.     hr=pIViewObject2->Draw(m_fe.dwAspect, -1, NULL, ptd, hIC, hDC
  521.         , &rcl, NULL, NULL, 0);
  522.     pIViewObject2->Release();
  523.     /*
  524.      * If Draw failed, then perhaps it couldn't work for the device,
  525.      * so try good old OleDraw as a last resort.  The code will
  526.      * generally be OLE_E_BLANK.
  527.      */
  528.     if (FAILED(hr))
  529.         OleDraw(m_pObj, m_fe.dwAspect, hDC, &rc);
  530.     if (!fPrinter && TENANTSTATE_SELECTED & m_dwState)
  531.         {
  532.         /*
  533.          * Draw sizing handles to show the selection state.  We
  534.          * convert things to MM_TEXT since that's what this
  535.          * function expects.
  536.          */
  537.         RectConvertMappings(&rc, NULL, TRUE);
  538.         uMM=SetMapMode(hDC, MM_TEXT);
  539.         UIDrawHandles(&rc, hDC, UI_HANDLES_INSIDE
  540.             | UI_HANDLES_NOBORDER| UI_HANDLES_USEINVERSE
  541.             , CXYHANDLE, TRUE);
  542.         uMM=SetMapMode(hDC, uMM);
  543.         }
  544.     return;
  545.     }
  546. /*
  547.  * CTenant::Repaint
  548.  * CTenant::Invalidate
  549.  *
  550.  * Purpose:
  551.  *  Repaints the tenant where it lies or invalidates its area
  552.  *  for later repainting.
  553.  *
  554.  * Parameters:
  555.  *  None
  556.  *
  557.  * Return Value:
  558.  *  None
  559.  */
  560. void CTenant::Repaint(void)
  561.     {
  562.     RECT        rc;
  563.     HDC         hDC;
  564.     hDC=GetDC(m_hWnd);
  565.     SetRect(&rc, m_pPG->m_xPos, m_pPG->m_yPos, 0, 0);
  566.     RectConvertMappings(&rc, NULL, FALSE);
  567.     SetMapMode(hDC, MM_LOMETRIC);
  568.     Draw(hDC, NULL, NULL, rc.left, rc.top, FALSE, FALSE);
  569.     ReleaseDC(m_hWnd, hDC);
  570.     return;
  571.     }
  572. void CTenant::Invalidate(void)
  573.     {
  574.     RECTL       rcl;
  575.     RECT        rc;
  576.     RectGet(&rcl, TRUE);
  577.     RECTFROMRECTL(rc, rcl);
  578.     OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);
  579.     InvalidateRect(m_hWnd, &rc, FALSE);
  580.     return;
  581.     }
  582. /*
  583.  * CTenant::ObjectGet
  584.  *
  585.  * Purpose:
  586.  *  Retrieves the LPUNKNOWN of the object in use by this tenant
  587.  *
  588.  * Parameters:
  589.  *  ppUnk           LPUNKNOWN * in which to return the object
  590.  *                  pointer.
  591.  *
  592.  * Return Value:
  593.  *  None
  594.  */
  595. void CTenant::ObjectGet(LPUNKNOWN *ppUnk)
  596.     {
  597.     if (NULL!=ppUnk)
  598.         {
  599.         *ppUnk=m_pObj;
  600.         m_pObj->AddRef();
  601.         }
  602.     return;
  603.     }
  604. /*
  605.  * CTenant::FormatEtcGet
  606.  *
  607.  * Purpose:
  608.  *  Retrieves the FORMATETC in use by this tenant
  609.  *
  610.  * Parameters:
  611.  *  pFE             LPFORMATETC in which to store the information.
  612.  *  fPresentation   BOOL indicating if we want the real format or
  613.  *                  that of the presentation.
  614.  *
  615.  * Return Value:
  616.  *  None
  617.  */
  618. void CTenant::FormatEtcGet(LPFORMATETC pFE, BOOL fPresentation)
  619.     {
  620.     if (NULL!=pFE)
  621.         *pFE=m_fe;
  622.     return;
  623.     }
  624. /*
  625.  * CTenant::SizeGet
  626.  * CTenant::SizeSet
  627.  * CTenant::RectGet
  628.  * CTenant::RectSet
  629.  *
  630.  * Purpose:
  631.  *  Returns or sets the size/position of the object contained here.
  632.  *
  633.  * Parameters:
  634.  *  pszl/prcl       LPSIZEL (Size) or LPRECTL (Rect) with the
  635.  *                  extents of interest.  In Get situations,
  636.  *                  this will receive the extents; in Set it
  637.  *                  contains the extents.
  638.  *  fDevice         BOOL indicating that pszl/prcl is expressed
  639.  *                  in device units.  Otherwise it's LOMETRIC.
  640.  *
  641.  * Return Value:
  642.  *  None
  643.  */
  644. void CTenant::SizeGet(LPSIZEL pszl, BOOL fDevice)
  645.     {
  646.     if (!fDevice)
  647.         {
  648.         pszl->cx=m_rcl.right-m_rcl.left;
  649.         pszl->cy=m_rcl.bottom-m_rcl.top;
  650.         }
  651.     else
  652.         {
  653.         RECT        rc;
  654.         SetRect(&rc, (int)(m_rcl.right-m_rcl.left)
  655.             , (int)(m_rcl.bottom-m_rcl.top), 0, 0);
  656.         RectConvertMappings(&rc, NULL, TRUE);
  657.         pszl->cx=(long)rc.left;
  658.         pszl->cy=(long)rc.top;
  659.         }
  660.     return;
  661.     }
  662. void CTenant::SizeSet(LPSIZEL pszl, BOOL fDevice)
  663.     {
  664.     SIZEL           szl;
  665.     if (!fDevice)
  666.         {
  667.         szl=*pszl;
  668.         m_rcl.right =pszl->cx+m_rcl.left;
  669.         m_rcl.bottom=pszl->cy+m_rcl.top;
  670.         }
  671.     else
  672.         {
  673.         RECT        rc;
  674.         SetRect(&rc, (int)pszl->cx, (int)pszl->cy, 0, 0);
  675.         RectConvertMappings(&rc, NULL, FALSE);
  676.         m_rcl.right =(long)rc.left+m_rcl.left;
  677.         m_rcl.bottom=(long)rc.top+m_rcl.top;
  678.         SETSIZEL(szl, (long)rc.left, (long)rc.top);
  679.         }
  680.     //Tell OLE that this object was resized.
  681.     if (NULL!=m_pObj)
  682.         {
  683.         HRESULT     hr;
  684.         LPOLEOBJECT pIOleObject;
  685.         hr=m_pObj->QueryInterface(IID_IOleObject
  686.             , (PPVOID)&pIOleObject);
  687.         if (SUCCEEDED(hr))
  688.             {
  689.             //Convert our LOMETRIC into HIMETRIC by *=10
  690.             szl.cx*=10;
  691.             szl.cy*=-10;    //Our size is stored negative.
  692.             pIOleObject->SetExtent(m_fe.dwAspect, &szl);
  693.             pIOleObject->Release();
  694.             }
  695.         }
  696.     return;
  697.     }
  698. void CTenant::RectGet(LPRECTL prcl, BOOL fDevice)
  699.     {
  700.     if (!fDevice)
  701.         *prcl=m_rcl;
  702.     else
  703.         {
  704.         RECT        rc;
  705.         RECTFROMRECTL(rc, m_rcl);
  706.         RectConvertMappings(&rc, NULL, TRUE);
  707.         RECTLFROMRECT(*prcl, rc);
  708.         }
  709.     return;
  710.     }
  711. void CTenant::RectSet(LPRECTL prcl, BOOL fDevice)
  712.     {
  713.     SIZEL   szl;
  714.     LONG    cx, cy;
  715.     cx=m_rcl.right-m_rcl.left;
  716.     cy=m_rcl.bottom-m_rcl.top;
  717.     if (!fDevice)
  718.         m_rcl=*prcl;
  719.     else
  720.         {
  721.         RECT        rc;
  722.         RECTFROMRECTL(rc, *prcl);
  723.         RectConvertMappings(&rc, NULL, FALSE);
  724.         RECTLFROMRECT(m_rcl, rc);
  725.         }
  726.     //Tell ourselves that the size changed, if it did.
  727.     if ((m_rcl.right-m_rcl.left)!=cx || (m_rcl.bottom-m_rcl.top)!=cy)
  728.         {
  729.         SETSIZEL(szl, m_rcl.right-m_rcl.left, m_rcl.bottom-m_rcl.top);
  730.         SizeSet(&szl, FALSE);
  731.         }
  732.     return;
  733.     }
  734. /*
  735.  * CTenant::CreateStatic
  736.  * (Protected)
  737.  *
  738.  * Purpose:
  739.  *  Creates a new static bitmap or metafile object for this tenant
  740.  *  using a freeloading method allowing us to specify exactly which
  741.  *  type of data we want to paste since OleCreateStaticFromData
  742.  *  doesn't.
  743.  *
  744.  * Parameters:
  745.  *  pIDataObject    LPDATAOBJECT from which to paste.
  746.  *  pFE             LPFORMATETC describing the format to paste.
  747.  *  ppObj           LPUNKNOWN * into which we store the
  748.  *                  object pointer.
  749.  *
  750.  * Return Value:
  751.  *  HRESULT         NOERROR on success, error code otherwise.
  752.  */
  753. HRESULT CTenant::CreateStatic(LPDATAOBJECT pIDataObject
  754.     , LPFORMATETC pFE, LPUNKNOWN *ppObj)
  755.     {
  756.     HRESULT             hr;
  757.     STGMEDIUM           stm;
  758.     LPUNKNOWN           pIUnknown;
  759.     LPOLECACHE          pIOleCache;
  760.     LPPERSISTSTORAGE    pIPersistStorage;
  761.     CLSID               clsID;
  762.     *ppObj=NULL;
  763.     //Try to get the data desired as specified in pFE->cfFormat
  764.     hr=pIDataObject->GetData(pFE, &stm);
  765.     if (FAILED(hr))
  766.         return hr;
  767.     //Create the object to handle this data.
  768.     if (CF_METAFILEPICT==pFE->cfFormat)
  769.         clsID=CLSID_Picture_Metafile;
  770.     else
  771.         clsID=CLSID_Picture_Dib;
  772.     hr=CreateDataCache(NULL, clsID, IID_IUnknown
  773.         , (PPVOID)&pIUnknown);
  774.     if (FAILED(hr))
  775.         {
  776.         ReleaseStgMedium(&stm);
  777.         return hr;
  778.         }
  779.     m_clsID=clsID;
  780.     //Stuff the data into the object
  781.     pIUnknown->QueryInterface(IID_IPersistStorage
  782.         , (PPVOID)&pIPersistStorage);
  783.     pIPersistStorage->InitNew(m_pIStorage);
  784.     //Now that we have the cache object, shove the data into it.
  785.     pIUnknown->QueryInterface(IID_IOleCache, (PPVOID)&pIOleCache);
  786.     pIOleCache->Cache(pFE, ADVF_PRIMEFIRST, NULL);
  787.     hr=pIOleCache->SetData(pFE, &stm, TRUE);
  788.     pIOleCache->Release();
  789.     //Insure there is a persistent copy on the disk
  790.     WriteClassStg(m_pIStorage, m_clsID);
  791.     pIPersistStorage->Save(m_pIStorage, TRUE);
  792.     pIPersistStorage->SaveCompleted(NULL);
  793.     pIPersistStorage->Release();
  794.     //The cache owns this now.
  795.     ReleaseStgMedium(&stm);
  796.     if (FAILED(hr))
  797.         pIUnknown->Release();
  798.     else
  799.         *ppObj=pIUnknown;
  800.     return hr;
  801.     }