/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: iviewobj.cpp Abstract: Implementation of the IViewObject interface. --*/ #include "polyline.h" #include "unihelpr.h" #include "unkhlpr.h" /* * CImpIViewObject interface implementation */ IMPLEMENT_CONTAINED_INTERFACE(CPolyline, CImpIViewObject) /* * 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_PTR), DWORD_PTR dwContinue ) { HRESULT hr = S_OK; RECT rc; RECTL rectBoundsDP; BOOL bMetafile = FALSE; BOOL bDeleteDC = FALSE; HDC hLocalICDev = NULL; // //Delegate iconic and printed representations. // if (!((DVASPECT_CONTENT | DVASPECT_THUMBNAIL) & dwAspect)) { try { hr = m_pObj->m_pDefIViewObject->Draw(dwAspect, lindex, pvAspect, ptd, hICDev, hDC, pRectBounds, pRectWBounds, pfnContinue, dwContinue); } catch (...) { hr = E_POINTER; } } else { if ( NULL == hDC ) { hr = E_INVALIDARG; } else if ( NULL == pRectBounds ) { hr = E_POINTER; } else { try { if (hICDev == NULL) { hLocalICDev = CreateTargetDC(hDC, ptd); bDeleteDC = (hLocalICDev != hDC ); } else { hLocalICDev = hICDev; } if ( NULL == hLocalICDev ) { hr = E_UNEXPECTED; } else { rectBoundsDP = *pRectBounds; bMetafile = GetDeviceCaps(hDC, TECHNOLOGY) == DT_METAFILE; if (!bMetafile) { ::LPtoDP ( hLocalICDev, (LPPOINT)&rectBoundsDP, 2); SaveDC ( hDC ); } rc.top = rectBoundsDP.top; rc.left = rectBoundsDP.left; rc.bottom = rectBoundsDP.bottom; rc.right = rectBoundsDP.right; m_pObj->Draw(hDC, hLocalICDev, FALSE, TRUE, &rc); hr = S_OK; } } catch (...) { hr = E_POINTER; } } } if (bDeleteDC) ::DeleteDC(hLocalICDev); if (!bMetafile) RestoreDC(hDC, -1); return hr; } /* * 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 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 ) { HRESULT hr = S_OK; //Delegate anything for ICON or DOCPRINT aspects if (!((DVASPECT_CONTENT | DVASPECT_THUMBNAIL) & dwAspect)) { try { hr = m_pObj->m_pDefIViewObject->Freeze(dwAspect, lindex, pvAspect, pdwFreeze); } catch (...) { hr = E_POINTER; } return hr; } if (dwAspect & m_pObj->m_dwFrozenAspects) { hr = VIEW_S_ALREADY_FROZEN; try { *pdwFreeze = dwAspect + FREEZE_KEY_OFFSET; } catch (...) { hr = E_POINTER; } return hr; } m_pObj->m_dwFrozenAspects |= dwAspect; hr = S_OK; if (NULL != pdwFreeze) { try { *pdwFreeze=dwAspect + FREEZE_KEY_OFFSET; } catch (...) { hr = E_POINTER; } } return hr; } /* * 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 ) { HRESULT hr = S_OK; try { //Pass anything with DVASPECT_ICON or _DOCPRINT to the handler. if (!((DVASPECT_CONTENT | DVASPECT_THUMBNAIL) & dwAspects)) { hr = m_pObj->m_pDefIViewObject->SetAdvise(dwAspects, dwAdvf, pIAdviseSink); } } catch (...) { return E_POINTER; } //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 = NULL; } hr = S_OK; try { if (NULL != pIAdviseSink) { pIAdviseSink->AddRef(); } } catch (...) { hr = E_POINTER; } if (SUCCEEDED(hr)) { m_pObj->m_pIAdviseSink = pIAdviseSink; m_pObj->m_dwAdviseAspects = dwAspects; m_pObj->m_dwAdviseFlags = dwAdvf; } return hr; } /* * 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 ) { HRESULT hr = S_OK; BOOL fRefAdded = FALSE; try { if (NULL != ppAdvSink) { *ppAdvSink = m_pObj->m_pIAdviseSink; if (m_pObj->m_pIAdviseSink != NULL) { m_pObj->m_pIAdviseSink->AddRef(); fRefAdded = TRUE; } } if (NULL != pdwAspects) { *pdwAspects = m_pObj->m_dwAdviseAspects; } if (NULL != pdwAdvf) { *pdwAdvf = m_pObj->m_dwAdviseFlags; } } catch (...) { hr = E_POINTER; } if (FAILED(hr)) { if (fRefAdded) { m_pObj->m_pIAdviseSink->Release(); } } return hr; } /* * 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; HRESULT hr = S_OK; if (!(DVASPECT_CONTENT & dwAspect)) { try { hr = m_pObj->m_pDefIViewObject->GetExtent(dwAspect, lindex, ptd, pszl); } catch (...) { hr = E_POINTER; } return hr; } #ifdef USE_SAMPLE_IPOLYLIN10 m_pObj->m_pImpIPolyline->RectGet(&rc); #else CopyRect(&rc, &m_pObj->m_RectExt); #endif m_pObj->RectConvertMappings(&rc, FALSE); hr = S_OK; try { pszl->cx = rc.right-rc.left; pszl->cy = rc.bottom-rc.top; } catch (...) { hr = E_POINTER; } return hr; }