⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tenant.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
📖 第 1 页 / 共 5 页
字号:
 * (Protected)
 *
 * Purpose:
 *  Performs operations necessary after creating an object or
 *  reloading one from storage.
 *
 * Parameters:
 *  pObj            LPUNKNOWN of the object in this tenant.
 *  pFE             LPFORMATETC describing the graphic here.
 *  dwData          DWORD extra data.  If pFE->dwAspect==
 *                  DVASPECT_ICON then this is the iconic metafile.
 *
 * Return Value:
 *  BOOL            TRUE if the function succeeded, FALSE otherwise.
 */

BOOL CTenant::ObjectInitialize(LPUNKNOWN pObj, LPFORMATETC pFE
    , DWORD dwData)
    {
    HRESULT         hr;
    LPPERSIST       pIPersist=NULL;
    DWORD           dw;
    PCDocument      pDoc;
    TCHAR           szFile[CCHPATHMAX];
    LPOLELINK       pIOleLink=NULL;

    if (NULL==pObj || NULL==pFE)
        return FALSE;

    m_pObj=pObj;
    m_fe=*pFE;
    m_fe.ptd=NULL;
    m_dwState=TENANTSTATE_DEFAULT;

    /*
     * Determine the type:  Static or Embedded.  If Static,
     * this will have CLSID_Picture_Metafile or CLSID_Picture_Dib.
     * Otherwise it's embedded.  Later we'll add a case for links.
     */
    m_tType=TENANTTYPE_EMBEDDEDOBJECT;

    if (SUCCEEDED(pObj->QueryInterface(IID_IPersist
        , (PPVOID)&pIPersist)))
        {
        CLSID   clsid=CLSID_NULL;

        hr=pIPersist->GetClassID(&clsid);

        //If we don't have a CLSID, default to static
        if (FAILED(hr) || CLSID_Picture_Metafile==clsid
            || CLSID_Picture_Dib==clsid)
            m_tType=TENANTTYPE_STATIC;

        pIPersist->Release();
        }

    //Check if this is a linked object.
    if (SUCCEEDED(pObj->QueryInterface(IID_IOleLink
        , (PPVOID)&pIOleLink)))
        {
        LPMONIKER   pmk;

        hr=pIOleLink->GetSourceMoniker(&pmk);

        if (FAILED(hr) || NULL==pmk)
            m_tType=TENANTTYPE_STATIC;
        else
            {
            m_tType=TENANTTYPE_LINKEDOBJECT;
            pmk->Release();

            //Connect to the object if the source is running.
            pIOleLink->BindIfRunning();
            }

        pIOleLink->Release();
        }

    m_pIViewObject2=NULL;
    hr=pObj->QueryInterface(IID_IViewObject2
        , (PPVOID)&m_pIViewObject2);

    if (FAILED(hr))
        return FALSE;

    m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, m_pImpIAdviseSink);

    //We need an IOleObject most of the time, so get one here.
    m_pIOleObject=NULL;
    hr=pObj->QueryInterface(IID_IOleObject
         , (PPVOID)&m_pIOleObject);

    /*
     * Follow up object creation with advises and so forth.  If
     * we cannot get IOleObject here, then we know we can't do
     * any IOleObject actions from here on--object is static.
     */
    if (FAILED(hr))
        return TRUE;

    /*
     * Get the MiscStatus bits and check for OLEMISC_ONLYICONIC.
     * If set, force dwAspect in m_fe to DVASPECT_ICON so we
     * remember to draw it properly and do extents right.
     */
    m_pIOleObject->GetMiscStatus(m_fe.dwAspect, &m_grfMisc);

    if (OLEMISC_ONLYICONIC & m_grfMisc)
        m_fe.dwAspect=DVASPECT_ICON;

    /*
     * We could pass m_pImpIOleClientSite in an OleCreate* call, but
     * since this function could be called after OleLoad, we still
     * need to do this here, so it's always done here...
     */
    m_pIOleObject->SetClientSite(m_pImpIOleClientSite);
    m_pIOleObject->Advise(m_pImpIAdviseSink, &dw);

    OleSetContainedObject(m_pIOleObject, TRUE);

    /*
     * For IOleObject::SetHostNames we need the application name
     * and the document name (which is passed in the object
     * parameter).  The design of Patron doesn't give us nice
     * structured access to the name of the document we're in, so
     * I grab the parent of the Pages window (the document) and
     * send it DOCM_PDOCUMENT which returns us the pointer.
     * Roundabout, but it works.
     */

    pDoc=(PCDocument)SendMessage(GetParent(m_hWnd), DOCM_PDOCUMENT
        , 0, 0L);

    if (NULL!=pDoc)
        pDoc->FilenameGet(szFile, CCHPATHMAX);
    else
        szFile[0]=0;

    NotifyOfRename(szFile, NULL, NULL);

    /*
     * If we're creating an iconic aspect object and we have
     * an object from the Insert Object dialog, then we need to
     * store that iconic presentation in the cache, handled
     * with the utility function INOLE_SwitchDisplayAspect.  In
     * this case dwData is a handle to the metafile containing
     * the icon.  If dwData is NULL then we depend on the
     * server to provide the aspect, in which case we need
     * a view advise.
     */

    if (DVASPECT_ICON & m_fe.dwAspect)
        {
        DWORD           dw=DVASPECT_CONTENT;
        IAdviseSink    *pSink;

        pSink=(NULL==dwData) ? NULL : m_pImpIAdviseSink;

        INOLE_SwitchDisplayAspect(m_pIOleObject, &dw
            , DVASPECT_ICON, (HGLOBAL)(UINT)dwData, FALSE
            , (NULL!=dwData), pSink, NULL);
        }

    return TRUE;
    }




/*
 * CTenant::Open
 *
 * Purpose:
 *  Retrieves the IStorage associated with this tenant.  The
 *  IStorage is owned by the tenant and thus the tenant always
 *  holds a reference count.
 *
 *  If the storage is already open for this tenant, then this
 *  function will AddRef it; therefore the caller must always
 *  match an Open with a Close.
 *
 * Parameters:
 *  pIStorage       LPSTORAGE above this tenant (which has its
 *                  own storage).
 *
 * Return Value:
 *  BOOL            TRUE if opening succeeds, FALSE otherwise.
 */

BOOL CTenant::Open(LPSTORAGE pIStorage)
    {
    HRESULT     hr=NOERROR;
    DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE
                    | STGM_SHARE_EXCLUSIVE;
    OLECHAR     szTemp[32];

    if (NULL==m_pIStorage)
        {
        if (NULL==pIStorage)
            return FALSE;

        /*
         * Attempt to open the storage under this ID.  If there is
         * none, then create it.  In either case we end up with an
         * IStorage that we either save in pPage or release.
         */

        GetStorageName(szTemp);
        hr=pIStorage->OpenStorage(szTemp, NULL, dwMode, NULL, 0
            , &m_pIStorage);

        if (FAILED(hr))
            {
            hr=pIStorage->CreateStorage(szTemp, dwMode, 0, 0
                , &m_pIStorage);
            }
        }
    else
        m_pIStorage->AddRef();

    if (FAILED(hr))
        return FALSE;

    m_cOpens++;

    //Create these if we don't have them already.
    if (NULL==m_pImpIOleClientSite && NULL==m_pImpIAdviseSink)
        {
        m_pImpIOleClientSite=new CImpIOleClientSite(this, this);
        m_pImpIAdviseSink=new CImpIAdviseSink(this, this);

        //CHAPTER22MOD
        m_pImpIOleIPSite=new CImpIOleInPlaceSite(this, this);

        if (NULL==m_pImpIOleClientSite || NULL==m_pImpIAdviseSink
            || NULL==m_pImpIOleIPSite)
            return FALSE;
        //End CHAPTER22MOD
        }

    return TRUE;
    }




/*
 * CTenant::Close
 *
 * Purpose:
 *  Possibly commits the storage, then releases it reversing the
 *  reference count from Open.  If the reference on the storage
 *  goes to zero, the storage is forgotten.  However, the object we
 *  contain is still held and as long as it's active the storage
 *  remains alive.
 *
 * Parameters:
 *  fCommit         BOOL indicating if we're to commit.
 *
 * Return Value:
 *  None
 */

void CTenant::Close(BOOL fCommit)
    {
    if (fCommit)
        Update();

    if (NULL!=m_pIStorage)
        {
        m_pIStorage->Release();

        /*
         * We can't use a zero reference count to know when to NULL
         * this since other things might have AddRef'd the storage.
         */
        if (0==--m_cOpens)
            {
            m_pIStorage=NULL;

            //CHAPTER22MOD
            //OnInPlaceDeactivate releases this pointer.
            if (NULL!=m_pIOleIPObject)
                m_pIOleIPObject->InPlaceDeactivate();
            //End CHAPTER22MOD

            //Close the object saving if necessary
            if (NULL!=m_pIOleObject)
                {
                m_pIOleObject->Close(OLECLOSE_SAVEIFDIRTY);
                ReleaseInterface(m_pIOleObject);
                }

            //Release all other held pointers
            if (NULL!=m_pIViewObject2)
                {
                m_pIViewObject2->SetAdvise(m_fe.dwAspect, 0, NULL);
                ReleaseInterface(m_pIViewObject2);
                }

            //We know we only hold one ref from Create or Load
            ReleaseInterface(m_pObj);
            }
        }

    return;
    }




/*
 * CTenant::Update
 *
 * Purpose:
 *  Forces a common on the page if it's open.
 *
 * Parameters:
 *  None
 *
 * Return Value:
 *  BOOL            TRUE if the object is open, FALSE otherwise.
 */

BOOL CTenant::Update(void)
    {
    LPPERSISTSTORAGE    pIPS;

    if (NULL!=m_pIStorage)
        {
        /*
         * We need to OleSave again because we might have changed
         * the size or position of this tenant.  We also need to
         * save the rectangle on the page, since that's not known
         * to OLE.
         */
        m_pObj->QueryInterface(IID_IPersistStorage, (PPVOID)&pIPS);

        //This fails for static objects...so we improvise if so
        if (FAILED(OleSave(pIPS, m_pIStorage, TRUE)))
            {
            //This is essentially what OleSave does.
            WriteClassStg(m_pIStorage, m_clsID);
            pIPS->Save(m_pIStorage, TRUE);
            }

        pIPS->SaveCompleted(NULL);
        pIPS->Release();

        m_pIStorage->Commit(STGC_DEFAULT);
        }

    return FALSE;
    }





/*
 * CTenant::Destroy
 *
 * Purpose:
 *  Removes this page from the given storage.  The caller should
 *  eventually delete this CTenant object to free the object herein.
 *  Nothing is committed when being destroyed.
 *
 * Parameters:
 *  pIStorage       LPSTORAGE contianing this page on which to call
 *                  DestroyElement
 *
 * Return Value:
 *  None
 */

void CTenant::Destroy(LPSTORAGE pIStorage)
    {
    OLECHAR     szTemp[32];

    if (NULL!=pIStorage)
        {
        if (NULL!=m_pIOleObject)
            {
            //CHAPTER22MOD
            DeactivateInPlaceObject(TRUE);
            //End CHAPTER22MOD

            m_pIOleObject->Close(OLECLOSE_NOSAVE);
            }

        if (NULL!=m_pIStorage)
            {
            //Remove all reference/open counts on this storage.
            while (0!=m_cOpens)
                {
                m_pIStorage->Release();
                m_cOpens--;
                }
            }

        GetStorageName(szTemp);
        pIStorage->DestroyElement(szTemp);

        m_pIStorage=NULL;
        }

    return;
    }




/*
 * CTenant::Select
 *
 * Purpose:
 *  Selects or deselects the tenant.
 *
 * Parameters:
 *  fSelect         BOOL indicating the new state of the tenant.
 *  fActivate       BOOL indicating whether to activate or
 *                  deactivate an in-place object.  If TRUE, then
 *                  activation/deactivation will happen.  If
 *                  FALSE, no change in activation takes place.
 *
 * Return Value:
 *  None
 */

//CHAPTER22MOD
void CTenant::Select(BOOL fSelect, BOOL fActivate)
//End CHAPTER22MOD
    {
    BOOL        fWasSelected;
    DWORD       dwState;
    RECT        rc;
    HDC         hDC;

    fWasSelected=(BOOL)(TENANTSTATE_SELECTED & m_dwState);

    //Nothing to do when there's no change.
    if (fWasSelected==fSelect)
        return;

    dwState=m_dwState & ~TENANTSTATE_SELECTED;
    m_dwState=dwState | ((fSelect) ? TENANTSTATE_SELECTED : 0);

    /*
     * Draw sizing handles to show the selection state.  We convert
     * things to MM_TEXT since that's what this function expects.
     */

    RECTFROMRECTL(rc, m_rcl);
    RectConvertMappings(&rc, NULL, TRUE);
    OffsetRect(&rc, -(int)m_pPG->m_xPos, -(int)m_pPG->m_yPos);

    hDC=GetDC(m_hWnd);

    UIDrawHandles(&rc, hDC, UI_HANDLES_INSIDE
        | UI_HANDLES_NOBORDER | UI_HANDLES_USEINVERSE
        , CXYHANDLE, !fWasSelected);

    ReleaseDC(m_hWnd, hDC);

    if (fSelect)
        m_pPG->m_fDirty=TRUE;

    //CHAPTER22MOD
    if (fActivate)
        {
        if (!fSelect)
            DeactivateInPlaceObject(FALSE);
        else
            {
            if (m_grfMisc & OLEMISC_INSIDEOUT)
                {
                MSG     msg;
                DWORD   dw;

                //Include a message for in-place objects.
                msg.hwnd=NULL;
                msg.message=WM_LBUTTONDOWN;
                msg.wParam=0;
                msg.time=GetMessageTime();

                dw=GetMessagePos();
                msg.lParam=dw;
                SETPOINT(msg.pt, LOWORD(dw), HIWORD(dw));

                Activate(OLEIVERB_UIACTIVATE, &msg);
                }
            }
        }
    //End CHAPTER22MOD

    return;
    }




/*
 * CTenant::ShowAsOpen
 *
 * Purpose:
 *  Draws or removes the hatch pattern over an object.
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -