IVIEWOBJ.CPP
/* 
 * IVIEWOBJ.CPP 
 * Polyline Component Chapter 24 
 * 
 * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved 
 * 
 * Kraig Brockschmidt, Microsoft 
 * Internet  :  kraigb@microsoft.com 
 * Compuserve:  >INTERNET:kraigb@microsoft.com 
 */ 
 
 
#include "polyline.h" 
 
 
/* 
 * CImpIViewObject::CImpIViewObject 
 * CImpIViewObject::~CImpIViewObject 
 * 
 * Parameters (Constructor): 
 *  pObj            PCPolyline of the object we're in. 
 *  pUnkOuter       LPUNKNOWN to which we delegate. 
 */ 
 
CImpIViewObject::CImpIViewObject(PCPolyline pObj 
    , LPUNKNOWN pUnkOuter) 
    { 
    m_cRef=0; 
    m_pObj=pObj; 
    m_pUnkOuter=pUnkOuter; 
    return; 
    } 
 
CImpIViewObject::~CImpIViewObject(void) 
    { 
    return; 
    } 
 
 
 
 
/* 
 * CImpIViewObject::QueryInterface 
 * CImpIViewObject::AddRef 
 * CImpIViewObject::Release 
 * 
 * Purpose: 
 *  IUnknown members for CImpIViewObject object. 
 */ 
 
STDMETHODIMP CImpIViewObject::QueryInterface(REFIID riid, PPVOID ppv) 
    { 
    return m_pUnkOuter->QueryInterface(riid, ppv); 
    } 
 
 
STDMETHODIMP_(ULONG) CImpIViewObject::AddRef(void) 
    { 
    ++m_cRef; 
    return m_pUnkOuter->AddRef(); 
    } 
 
STDMETHODIMP_(ULONG) CImpIViewObject::Release(void) 
    { 
    --m_cRef; 
    return m_pUnkOuter->Release(); 
    } 
 
 
 
/* 
 * CImpIViewObject::Draw 
 * 
 * Purpose: 
 *  Draws the object on the given hDC specifically for the requested 
 *  aspect, device, and within the appropriate bounds. 
 * 
 * Parameters: 
 *  dwAspect        DWORD aspect to draw. 
 *  lindex          LONG index of the piece to draw. 
 *  pvAspect        LPVOID for extra information, always NULL. 
 *  ptd             DVTARGETDEVICE * containing device 
 *                  information. 
 *  hICDev          HDC containing the IC for the device. 
 *  hDC             HDC on which to draw. 
 *  pRectBounds     LPCRECTL describing the rectangle in which 
 *                  to draw. 
 *  pRectWBounds    LPCRECTL describing the placement rectangle 
 *                  if part of what you draw is another metafile. 
 *  pfnContinue     Function to call periodically during 
 *                  long repaints. 
 *  dwContinue      DWORD extra information to pass to the 
 *                  pfnContinue. 
 * 
 * Return Value: 
 *  HRESULT         NOERROR or a general error value. 
 */ 
 
STDMETHODIMP CImpIViewObject::Draw(DWORD dwAspect, LONG lindex 
    , LPVOID pvAspect, DVTARGETDEVICE *ptd, HDC hICDev 
    , HDC hDC, LPCRECTL pRectBounds, LPCRECTL pRectWBounds 
    , BOOL (CALLBACK *pfnContinue) (DWORD), DWORD dwContinue) 
    { 
    RECT            rc; 
    POLYLINEDATA    pl; 
    PPOLYLINEDATA   ppl=&m_pObj->m_pl; 
 
    RECTFROMRECTL(rc, *pRectBounds); 
 
    //Delegate iconic and printed representations. 
    if (!((DVASPECT_CONTENT | DVASPECT_THUMBNAIL) & dwAspect)) 
        { 
        return m_pObj->m_pDefIViewObject->Draw(dwAspect, lindex 
            , pvAspect, ptd, hICDev, hDC, pRectBounds, pRectWBounds 
            , pfnContinue, dwContinue); 
        } 
 
 
    /* 
     * If we're asked to draw a frozen aspect, use the data from 
     * a copy we made in IViewObject::Freeze.  Otherwise use the 
     * current data. 
     */ 
    if (dwAspect & m_pObj->m_dwFrozenAspects) 
        { 
        //Point to the data to actually use. 
        if (DVASPECT_CONTENT==dwAspect) 
            ppl=&m_pObj->m_plContent; 
        else 
            ppl=&m_pObj->m_plThumbnail; 
        } 
 
 
    //Make a copy so we can modify it (and not worry about threads) 
    memcpy(&pl, ppl, CBPOLYLINEDATA); 
 
    /* 
     * If we're going to a printer, check if it's color capable. 
     * if not, then use black on white for this figure. 
     */ 
    if (NULL!=hICDev) 
        { 
        if (GetDeviceCaps(hICDev, NUMCOLORS) <= 2) 
            { 
            pl.rgbBackground=RGB(255, 255, 255); 
            pl.rgbLine=RGB(0, 0, 0); 
            } 
        } 
 
    m_pObj->Draw(hDC, FALSE, TRUE, &rc, &pl); 
    return NOERROR; 
    } 
 
 
 
 
/* 
 * CImpIViewObject::GetColorSet 
 * 
 * Purpose: 
 *  Retrieves the color palette used by the object. 
 * 
 * Parameters: 
 *  dwAspect        DWORD aspect of interest. 
 *  lindex          LONG piece of interest. 
 *  pvAspect        LPVOID with extra information, always NULL. 
 *  ptd             DVTARGETDEVICE * containing device info. 
 *  hICDev          HDC containing the IC for the device. 
 *  ppColorSet      LPLOGPALETTE * into which to return the 
 *                  pointer to the palette in this color set. 
 * 
 * Return Value: 
 *  HRESULT         NOERROR or a general error value. 
 */ 
 
STDMETHODIMP CImpIViewObject::GetColorSet(DWORD dwDrawAspect 
    , LONG lindex, LPVOID pvAspect, DVTARGETDEVICE *ptd 
    , HDC hICDev, LPLOGPALETTE *ppColorSet) 
    { 
    return ResultFromScode(E_NOTIMPL); 
    } 
 
 
 
 
 
 
/* 
 * CImpIViewObject::Freeze 
 * 
 * Purpose: 
 *  Freezes the view of a particular aspect such that data 
 *  changes do not affect the view. 
 * 
 * Parameters: 
 *  dwAspect        DWORD aspect to freeze. 
 *  lindex          LONG piece index under consideration. 
 *  pvAspect        LPVOID for further information, always NULL. 
 *  pdwFreeze       LPDWORD in which to return the key. 
 * 
 * Return Value: 
 *  HRESULT         NOERROR or a general error value. 
 */ 
 
STDMETHODIMP CImpIViewObject::Freeze(DWORD dwAspect, LONG lindex 
    , LPVOID pvAspect, LPDWORD pdwFreeze) 
    { 
    //Delegate anything for ICON or DOCPRINT aspects 
    if (!((DVASPECT_CONTENT | DVASPECT_THUMBNAIL) & dwAspect)) 
        { 
        return m_pObj->m_pDefIViewObject->Freeze(dwAspect, lindex 
            , pvAspect, pdwFreeze); 
        } 
 
    if (dwAspect & m_pObj->m_dwFrozenAspects) 
        { 
        *pdwFreeze=dwAspect + FREEZE_KEY_OFFSET; 
        return ResultFromScode(VIEW_S_ALREADY_FROZEN); 
        } 
 
    m_pObj->m_dwFrozenAspects |= dwAspect; 
 
 
    /* 
     * For whatever aspects become frozen, make a copy of the data. 
     * Later when drawing, if such a frozen aspect is requested, 
     * we'll draw from this data rather than from our current data. 
     */ 
    if (DVASPECT_CONTENT & dwAspect) 
        { 
        memcpy(&m_pObj->m_plContent, &m_pObj->m_pl 
            , CBPOLYLINEDATA); 
        } 
 
    if (DVASPECT_THUMBNAIL & dwAspect) 
        { 
        memcpy(&m_pObj->m_plThumbnail, &m_pObj->m_pl 
            , CBPOLYLINEDATA); 
        } 
 
    if (NULL!=pdwFreeze) 
        *pdwFreeze=dwAspect + FREEZE_KEY_OFFSET; 
 
    return NOERROR; 
    } 
 
 
 
 
 
 
/* 
 * CImpIViewObject::Unfreeze 
 * 
 * Purpose: 
 *  Thaws an aspect frozen in ::Freeze.  We expect that a container 
 *  will redraw us after freezing if necessary, so we don't send 
 *  any sort of notification here. 
 * 
 * Parameters: 
 *  dwFreeze        DWORD key returned from ::Freeze. 
 * 
 * Return Value: 
 *  HRESULT         NOERROR or a general error value. 
 */ 
 
STDMETHODIMP CImpIViewObject::Unfreeze(DWORD dwFreeze) 
    { 
    DWORD       dwAspect=dwFreeze - FREEZE_KEY_OFFSET; 
 
    //Delegate anything for ICON or DOCPRINT aspects 
    if (!((DVASPECT_CONTENT | DVASPECT_THUMBNAIL) & dwAspect)) 
        m_pObj->m_pDefIViewObject->Unfreeze(dwFreeze); 
 
    //The aspect to unfreeze is in the key. 
    m_pObj->m_dwFrozenAspects &= ~(dwAspect); 
 
    /* 
     * Since we always kept our current data up to date, we don't 
     * have to do anything thing here like requesting data again. 
     * Because we removed dwAspect from m_dwFrozenAspects, Draw 
     * will again use the current data. 
     */ 
 
    return NOERROR; 
    } 
 
 
 
 
 
/* 
 * CImpIViewObject::SetAdvise 
 * 
 * Purpose: 
 *  Provides an advise sink to the view object enabling 
 *  notifications for a specific aspect. 
 * 
 * Parameters: 
 *  dwAspects       DWORD describing the aspects of interest. 
 *  dwAdvf          DWORD containing advise flags. 
 *  pIAdviseSink    LPADVISESINK to notify. 
 * 
 * Return Value: 
 *  HRESULT         NOERROR or a general error value. 
 */ 
 
STDMETHODIMP CImpIViewObject::SetAdvise(DWORD dwAspects, DWORD dwAdvf 
    , LPADVISESINK pIAdviseSink) 
    { 
    //Pass anything with DVASPECT_ICON or _DOCPRINT to the handler. 
    if (!((DVASPECT_CONTENT | DVASPECT_THUMBNAIL) & dwAspects)) 
        { 
        m_pObj->m_pDefIViewObject->SetAdvise(dwAspects, dwAdvf 
            , pIAdviseSink); 
        } 
 
    //We continue because dwAspects may have more than one in it. 
    if (NULL!=m_pObj->m_pIAdviseSink) 
        m_pObj->m_pIAdviseSink->Release(); 
 
    m_pObj->m_pIAdviseSink=pIAdviseSink; 
    m_pObj->m_dwAdviseAspects=dwAspects; 
    m_pObj->m_dwAdviseFlags=dwAdvf; 
 
    if (NULL!=m_pObj->m_pIAdviseSink) 
        m_pObj->m_pIAdviseSink->AddRef(); 
 
    return NOERROR; 
    } 
 
 
 
 
/* 
 * CImpIViewObject::GetAdvise 
 * 
 * Purpose: 
 *  Returns the last known IAdviseSink seen by ::SetAdvise. 
 * 
 * Parameters: 
 *  pdwAspects      LPDWORD in which to store the last 
 *                  requested aspects. 
 *  pdwAdvf         LPDWORD in which to store the last 
 *                  requested flags. 
 *  ppIAdvSink      LPADVISESINK * in which to store the 
 *                  IAdviseSink. 
 * 
 * Return Value: 
 *  HRESULT         NOERROR or a general error value. 
 */ 
 
STDMETHODIMP CImpIViewObject::GetAdvise(LPDWORD pdwAspects 
    , LPDWORD pdwAdvf, LPADVISESINK *ppAdvSink) 
    { 
    if (NULL!=ppAdvSink) 
        { 
        *ppAdvSink=m_pObj->m_pIAdviseSink; 
        m_pObj->m_pIAdviseSink->AddRef(); 
        } 
 
    if (NULL!=pdwAspects) 
        *pdwAspects=m_pObj->m_dwAdviseAspects; 
 
    if (NULL!=pdwAdvf) 
        *pdwAdvf=m_pObj->m_dwAdviseFlags; 
 
    return NOERROR; 
    } 
 
 
 
 
/* 
 * CImpIViewObject::GetExtent 
 * 
 * Purpose: 
 *  Retrieves the extents of the object's display. 
 * 
 * Parameters: 
 *  dwAspect        DWORD of the aspect of interest. 
 *  lindex          LONG index of the piece of interest. 
 *  ptd             DVTARGETDEVICE * with device information. 
 *  pszl            LPSIZEL to the structure in which to return 
 *                  the extents. 
 * 
 * Return Value: 
 *  HRESULT         NOERROR or a general error value. 
 */ 
 
STDMETHODIMP CImpIViewObject::GetExtent(DWORD dwAspect, LONG lindex 
    , DVTARGETDEVICE *ptd, LPSIZEL pszl) 
    { 
    RECT            rc; 
 
    if (!(DVASPECT_CONTENT & dwAspect)) 
        { 
        return m_pObj->m_pDefIViewObject->GetExtent(dwAspect 
            , lindex, ptd, pszl); 
        } 
 
    m_pObj->m_pImpIPolyline->RectGet(&rc); 
    m_pObj->RectConvertMappings(&rc, FALSE); 
 
    pszl->cx=rc.right-rc.left; 
    pszl->cy=rc.bottom-rc.top; 
 
    return NOERROR; 
    }