|
|
/*++
Copyright (C) 1993-1999 Microsoft Corporation
Module Name:
polyline.cpp
Abstract:
Implementation of the CPolyline class that is exposed as a component object.
--*/
#include "polyline.h"
#include "smonctrl.h"
#include "unihelpr.h"
#include "utils.h"
extern ITypeLib *g_pITypeLib;
/*
* CPolyline:CPolyline * CPolyline::~CPolyline * * Constructor Parameters: * pUnkOuter LPUNKNOWN of the controlling unknown. * pfnDestroy PFNDESTROYED to call when an object is * destroyed. * hInst HINSTANCE of the application we're in. */
CPolyline::CPolyline ( LPUNKNOWN pUnkOuter, PFNDESTROYED pfnDestroy ) : m_cRef ( 0 ), m_pUnkOuter ( pUnkOuter ), m_pfnDestroy ( pfnDestroy ), m_fDirty ( FALSE ), #ifdef USE_SAMPLE_IPOLYLIN10
m_pImpIPolyline ( NULL ), #endif
m_pImpIConnPtCont ( NULL ), m_cf ( 0 ), m_clsID ( CLSID_SystemMonitor ), m_pIStorage ( NULL ), m_pIStream ( NULL ), m_pImpIPersistStorage ( NULL ), m_pImpIPersistStreamInit ( NULL ), m_pImpIPersistPropertyBag ( NULL ), m_pImpIPerPropertyBrowsing ( NULL ), m_pImpIDataObject ( NULL ), m_pImpIObjectSafety ( NULL ), m_pIDataAdviseHolder ( NULL ), m_pDefIUnknown ( NULL ), m_pDefIDataObject ( NULL ), m_pDefIViewObject ( NULL ), m_pDefIPersistStorage ( NULL ), m_pIOleAdviseHolder ( NULL ), m_pImpIOleObject ( NULL ), m_pIOleClientSite ( NULL ), m_pImpIViewObject ( NULL ), m_pIAdviseSink ( NULL ), m_dwFrozenAspects ( 0 ), m_dwAdviseAspects ( 0 ), m_dwAdviseFlags ( 0 ), m_pImpIRunnableObject ( NULL ), m_bIsRunning ( FALSE ), // m_pImpIExternalConnection ( NULL ),
m_fLockContainer ( FALSE ), m_dwRegROT ( 0L ), m_pIOleIPSite ( NULL ), m_pIOleIPFrame ( NULL ), m_pIOleIPUIWindow ( NULL ), m_pImpIOleIPObject ( NULL ), m_pImpIOleIPActiveObject ( NULL ), m_hMenuShared ( NULL ), m_hOLEMenu ( NULL ), m_pHW ( NULL ), m_fAllowInPlace ( TRUE ), m_fUIActive ( FALSE ), m_fContainerKnowsInsideOut ( FALSE ), m_pImpISpecifyPP ( NULL ), m_pImpIProvideClassInfo ( NULL ), m_pImpIDispatch ( NULL ), m_pImpISystemMonitor ( NULL ), m_pImpIOleControl ( NULL ), m_pImpICounters ( NULL ), m_pImpILogFiles ( NULL ), m_pITypeLib ( NULL ), m_pIOleControlSite ( NULL ), m_pIDispatchAmbients ( NULL ), m_fFreezeEvents ( FALSE ), m_fHatch ( TRUE ), m_pCtrl ( NULL ) { // Set default extents
SetRect(&m_RectExt, 0, 0, 300, 200); return; }
CPolyline::~CPolyline(void) { LPUNKNOWN pIUnknown=this;
if (NULL!=m_pUnkOuter) pIUnknown=m_pUnkOuter;
if (NULL!=m_pHW) { delete m_pHW; m_pHW = NULL; }
if (NULL != m_pCtrl) { delete m_pCtrl; m_pCtrl = NULL; } /*
* In aggregation, release cached pointers but * AddRef the controlling unknown first. */
pIUnknown->AddRef(); pIUnknown->AddRef(); pIUnknown->AddRef();
ReleaseInterface(m_pDefIViewObject); ReleaseInterface(m_pDefIDataObject); ReleaseInterface(m_pDefIPersistStorage);
//Cached pointer rules do not apply to IUnknown
ReleaseInterface(m_pDefIUnknown);
ReleaseInterface(m_pIAdviseSink); ReleaseInterface(m_pIOleClientSite); ReleaseInterface(m_pIOleAdviseHolder);
DeleteInterfaceImp(m_pImpIOleObject); DeleteInterfaceImp(m_pImpIViewObject); DeleteInterfaceImp(m_pImpIRunnableObject);
//Other in-place interfaces released in deactivation.
DeleteInterfaceImp(m_pImpIOleIPObject); DeleteInterfaceImp(m_pImpIOleIPActiveObject);
ReleaseInterface(m_pIDispatchAmbients); ReleaseInterface(m_pIOleControlSite);
DeleteInterfaceImp(m_pImpISpecifyPP); DeleteInterfaceImp(m_pImpIProvideClassInfo); DeleteInterfaceImp(m_pImpIDispatch); DeleteInterfaceImp(m_pImpISystemMonitor); DeleteInterfaceImp(m_pImpIOleControl); DeleteInterfaceImp(m_pImpICounters); DeleteInterfaceImp(m_pImpILogFiles);
//Anything we might have registered in IRunnableObject::Run
if (m_dwRegROT != 0) { IRunningObjectTable *pROT;
if (!FAILED(GetRunningObjectTable(0, &pROT))) { pROT->Revoke(m_dwRegROT); pROT->Release(); } }
// DeleteInterfaceImp(m_pImpIExternalConnection);
ReleaseInterface(m_pIDataAdviseHolder); DeleteInterfaceImp(m_pImpIDataObject); DeleteInterfaceImp(m_pImpIObjectSafety);
DeleteInterfaceImp(m_pImpIPersistStreamInit); DeleteInterfaceImp(m_pImpIPersistStorage); DeleteInterfaceImp(m_pImpIPersistPropertyBag); DeleteInterfaceImp(m_pImpIPerPropertyBrowsing); ReleaseInterface(m_pIStream); ReleaseInterface(m_pIStorage);
DeleteInterfaceImp(m_pImpIConnPtCont); #ifdef USE_SAMPLE_IPOLYLIN10
DeleteInterfaceImp(m_pImpIPolyline); #endif
return; }
/*
* CPolyline::Init * * Purpose: * Performs any intiailization of a CPolyline that's prone to * failure that we also use internally before exposing the * object outside this DLL. * * Parameters: * None * * Return Value: * BOOL TRUE if the function is successful, * FALSE otherwise. */
BOOL CPolyline::Init(void) { LPUNKNOWN pIUnknown=this; HRESULT hr; INT i;
if (NULL!=m_pUnkOuter) pIUnknown=m_pUnkOuter;
m_cf=(CLIPFORMAT)RegisterClipboardFormat(SZSYSMONCLIPFORMAT);
m_pImpIPersistStorage=new CImpIPersistStorage(this, pIUnknown);
if (NULL==m_pImpIPersistStorage) return FALSE;
m_pImpIPersistStreamInit=new CImpIPersistStreamInit(this, pIUnknown);
if (NULL==m_pImpIPersistStreamInit) return FALSE;
m_pImpIPersistPropertyBag=new CImpIPersistPropertyBag(this, pIUnknown);
if (NULL==m_pImpIPersistPropertyBag) return FALSE;
m_pImpIPerPropertyBrowsing=new CImpIPerPropertyBrowsing(this, pIUnknown);
if (NULL==m_pImpIPerPropertyBrowsing) return FALSE;
#ifdef USE_SAMPLE_IPOLYLIN10
m_pImpIPolyline=new CImpIPolyline(this, pIUnknown);
if (NULL==m_pImpIPolyline) return FALSE; #endif
m_pImpIConnPtCont=new CImpIConnPtCont(this, pIUnknown);
if (NULL==m_pImpIConnPtCont) return FALSE;
for (i=0; i<CONNECTION_POINT_CNT; i++) { if (!m_ConnectionPoint[i].Init(this, pIUnknown, i)) { return FALSE; } }
m_pImpIDataObject=new CImpIDataObject(this, pIUnknown);
if (NULL==m_pImpIDataObject) return FALSE;
m_pImpIOleObject=new CImpIOleObject(this, pIUnknown);
if (NULL==m_pImpIOleObject) return FALSE;
m_pImpIViewObject=new CImpIViewObject(this, pIUnknown);
if (NULL==m_pImpIViewObject) return FALSE;
m_pImpIRunnableObject=new CImpIRunnableObject(this, pIUnknown);
if (NULL==m_pImpIRunnableObject) return FALSE;
/***********************************
m_pImpIExternalConnection=new CImpIExternalConnection(this , pIUnknown);
if (NULL==m_pImpIExternalConnection) return FALSE; ************************************/
m_pImpIOleIPObject=new CImpIOleInPlaceObject(this, pIUnknown);
if (NULL==m_pImpIOleIPObject) return FALSE;
m_pImpIOleIPActiveObject=new CImpIOleInPlaceActiveObject(this , pIUnknown);
if (NULL==m_pImpIOleIPActiveObject) return FALSE;
m_pImpISpecifyPP=new CImpISpecifyPP(this, pIUnknown);
if (NULL==m_pImpISpecifyPP) return FALSE;
m_pImpIProvideClassInfo=new CImpIProvideClassInfo(this, pIUnknown);
if (NULL==m_pImpIProvideClassInfo) return FALSE;
m_pImpISystemMonitor=new CImpISystemMonitor(this, pIUnknown);
if (NULL==m_pImpISystemMonitor) return FALSE;
m_pImpICounters = new CImpICounters(this, pIUnknown);
if (NULL==m_pImpICounters) return FALSE;
m_pImpILogFiles = new CImpILogFiles(this, pIUnknown);
if (NULL==m_pImpILogFiles) return FALSE;
m_pImpIDispatch=new CImpIDispatch(this, pIUnknown);
if (NULL==m_pImpIDispatch) return FALSE;
m_pImpIDispatch->SetInterface(DIID_DISystemMonitor, m_pImpISystemMonitor);
m_pImpIOleControl=new CImpIOleControl(this, pIUnknown);
if (NULL==m_pImpIOleControl) return FALSE; m_pImpIObjectSafety = new CImpIObjectSafety(this, pIUnknown); if (NULL == m_pImpIObjectSafety) { return FALSE; }
m_pCtrl = new CSysmonControl(this); if (NULL==m_pCtrl) return FALSE; if ( !m_pCtrl->AllocateSubcomponents() ) return FALSE;
/*
* We're sitting at ref count 0 and the next call will AddRef a * few times and Release a few times. This insures we don't * delete ourselves prematurely. */ m_cRef++;
//
// Aggregate OLE's cache for IOleCache* interfaces.
//
hr = CreateDataCache(pIUnknown, CLSID_SystemMonitor , IID_IUnknown, (PPVOID)&m_pDefIUnknown);
if (FAILED(hr)) return FALSE;
/*
* NOTE: The spec specifically states that any interfaces * besides IUnknown that we obtain on an aggregated object * should be Released immediately after we QueryInterface for * them because the QueryInterface will AddRef us, and since * we would not release these interfaces until we were * destroyed, we'd never go away because we'd never get a zero * ref count. */
//Now try to get other interfaces to which we delegate
hr=m_pDefIUnknown->QueryInterface(IID_IViewObject2 , (PPVOID)&m_pDefIViewObject);
if (FAILED(hr)) return FALSE;
pIUnknown->Release();
hr=m_pDefIUnknown->QueryInterface(IID_IDataObject , (PPVOID)&m_pDefIDataObject);
if (FAILED(hr)) return FALSE;
pIUnknown->Release();
hr=m_pDefIUnknown->QueryInterface(IID_IPersistStorage , (PPVOID)&m_pDefIPersistStorage);
if (FAILED(hr)) return FALSE;
pIUnknown->Release();
m_cRef--;
#ifdef USE_SAMPLE_IPOLYLIN10
m_pImpIPolyline->New(); #endif
/*
* The type information lib already loaded in DllAttach * just use it.(AddRef on it is called in DllAttach) * */ m_pITypeLib = g_pITypeLib;
//Set up our CONTROLINFO structure (we have two mnemonics)
m_ctrlInfo.cb=sizeof(CONTROLINFO); m_ctrlInfo.dwFlags=0; m_ctrlInfo.hAccel=NULL; m_ctrlInfo.cAccel=0;
/*
* Note: we cannot initialize ambients until we get * a container interface pointer in IOleObject::SetClientSite. */
return TRUE; }
/*
* CPolyline::QueryInterface * CPolyline::AddRef * CPolyline::Release * * Purpose: * IUnknown members for CPolyline object. */
STDMETHODIMP CPolyline::QueryInterface( REFIID riid, PPVOID ppv ) { HRESULT hr = S_OK;
try { *ppv=NULL;
if (IID_IUnknown==riid) *ppv=this;
else if (IID_IConnectionPointContainer==riid) *ppv=m_pImpIConnPtCont;
else if (IID_IPersistStorage==riid) *ppv=m_pImpIPersistStorage;
else if (IID_IPersist==riid || IID_IPersistStream==riid || IID_IPersistStreamInit==riid) *ppv=m_pImpIPersistStreamInit;
else if (IID_IPersistPropertyBag==riid ) *ppv=m_pImpIPersistPropertyBag;
else if (IID_IPerPropertyBrowsing==riid ) *ppv=m_pImpIPerPropertyBrowsing; else if (IID_IDataObject==riid) *ppv=m_pImpIDataObject;
else if (IID_IOleObject==riid) *ppv=m_pImpIOleObject;
else if (IID_IViewObject==riid || IID_IViewObject2==riid) *ppv=m_pImpIViewObject;
else if (IID_IRunnableObject==riid) // *ppv=m_pImpIRunnableObject;
return E_NOINTERFACE;
else if (IID_IExternalConnection==riid) // *ppv=m_pImpIExternalConnection;
return E_NOINTERFACE;
//IOleWindow will be the InPlaceObject
else if (IID_IOleWindow==riid || IID_IOleInPlaceObject==riid) *ppv=m_pImpIOleIPObject;
// The OLE rule state that InPlaceActiveObject should not be
// provided in response to a query, but the current MFC (4.0)
// won't work if we don't do it.
else if (IID_IOleInPlaceActiveObject==riid) *ppv=m_pImpIOleIPActiveObject;
else if (IID_ISpecifyPropertyPages==riid) *ppv=m_pImpISpecifyPP;
else if (IID_IProvideClassInfo==riid) *ppv=m_pImpIProvideClassInfo;
else if (IID_IDispatch==riid || DIID_DISystemMonitor==riid) *ppv=m_pImpIDispatch;
else if (IID_ISystemMonitor==riid) *ppv=m_pImpISystemMonitor;
else if (IID_IOleControl==riid) *ppv=m_pImpIOleControl;
//Use the default handler's cache.
else if (IID_IOleCache==riid || IID_IOleCache2==riid) return m_pDefIUnknown->QueryInterface(riid, ppv); else if (IID_IObjectSafety == riid) { *ppv = m_pImpIObjectSafety; } else { hr = E_NOINTERFACE; }
} catch (...) { hr = E_POINTER; }
assert ( NULL != *ppv ); if (SUCCEEDED(hr) && NULL != *ppv ) { ((LPUNKNOWN)*ppv)->AddRef(); }
return hr; }
STDMETHODIMP_(ULONG) CPolyline::AddRef(void) { return ++m_cRef; }
STDMETHODIMP_(ULONG) CPolyline::Release(void) { if (0L!=--m_cRef) return m_cRef;
// Prevent reentrant call
m_cRef++;
if (NULL!=m_pfnDestroy) (*m_pfnDestroy)();
delete this; return 0L; }
/*
* CPolyline::RectConvertMappings * * Purpose: * Converts the contents of a rectangle from device (MM_TEXT) or * HIMETRIC to the other. * * Parameters: * pRect LPRECT containing the rectangle to convert. * fToDevice BOOL TRUE to convert from HIMETRIC to device, * FALSE to convert device to HIMETRIC. * * Return Value: * None */
void CPolyline::RectConvertMappings( LPRECT pRect, BOOL fToDevice ) { HDC hDC = NULL; INT iLpx, iLpy;
if ( NULL != pRect ) {
hDC=GetDC(NULL);
if ( NULL != hDC ) { iLpx=GetDeviceCaps(hDC, LOGPIXELSX); iLpy=GetDeviceCaps(hDC, LOGPIXELSY); ReleaseDC(NULL, hDC);
if (fToDevice) { pRect->left=MulDiv(iLpx, pRect->left, HIMETRIC_PER_INCH); pRect->top =MulDiv(iLpy, pRect->top , HIMETRIC_PER_INCH);
pRect->right =MulDiv(iLpx, pRect->right, HIMETRIC_PER_INCH); pRect->bottom=MulDiv(iLpy, pRect->bottom,HIMETRIC_PER_INCH); } else { if ( 0 != iLpx && 0 != iLpy ) { pRect->left=MulDiv(pRect->left, HIMETRIC_PER_INCH, iLpx); pRect->top =MulDiv(pRect->top , HIMETRIC_PER_INCH, iLpy);
pRect->right =MulDiv(pRect->right, HIMETRIC_PER_INCH, iLpx); pRect->bottom=MulDiv(pRect->bottom,HIMETRIC_PER_INCH, iLpy); } } } } return; }
/*
* CPolyline::RenderBitmap * * Purpose: * Creates a bitmap image of the current Polyline. * * Parameters: * phBmp HBITMAP * in which to return the bitmap. * * Return Value: * HRESULT NOERROR if successful, otherwise a * POLYLINE_E_ value. */
STDMETHODIMP CPolyline::RenderBitmap( HBITMAP *phBmp, HDC hAttribDC ) { //HDC hDC;
HRESULT hr = NOERROR; HDC hMemDC; HBITMAP hBmp = NULL; RECT rc; HGDIOBJ hObj; HWND hWnd;
if (NULL==phBmp) { hr = E_POINTER; } else if ( NULL == hAttribDC ) { hr = E_INVALIDARG; } else { hWnd = m_pCtrl->Window();
if ( NULL != hWnd ) {
//Render a bitmap the size of the current rectangle.
hMemDC = CreateCompatibleDC(hAttribDC);
if ( NULL != hMemDC ) { GetClientRect(hWnd, &rc); hBmp = CreateCompatibleBitmap(hAttribDC, rc.right, rc.bottom);
if (NULL!=hBmp) { //Draw the control into the bitmap.
hObj = SelectObject(hMemDC, hBmp); Draw(hMemDC, hAttribDC, FALSE, TRUE, &rc); SelectObject(hMemDC, hObj); }
DeleteDC(hMemDC); // ReleaseDC(hWnd, hDC);
} *phBmp=hBmp; hr = NOERROR; } else { hr = E_UNEXPECTED; } } return hr; }
/*
* CPolyline::RenderMetafilePict * * Purpose: * Renders the current Polyline into a METAFILEPICT structure in * global memory. * * Parameters: * phMem HGLOBAL * in which to return the * METAFILEPICT. * * Return Value: * HRESULT NOERROR if successful, otherwise a * POLYLINE_E_ value. */
STDMETHODIMP CPolyline::RenderMetafilePict( HGLOBAL *phMem, HDC hAttribDC ) { HGLOBAL hMem; HMETAFILE hMF; LPMETAFILEPICT pMF; RECT rc; HDC hDC;
if (NULL==phMem) return E_POINTER;
//Create a memory metafile and return its handle.
hDC=(HDC)CreateMetaFile(NULL);
if (NULL==hDC) return STG_E_MEDIUMFULL;
SetMapMode(hDC, MM_ANISOTROPIC);
//
// Always set up the window extents to the real window size
// so the drawing routines can work in their normal dev coords
//
/********* Use the extent rect, not the window rect *********/ rc = m_RectExt; // GetClientRect(m_pCtrl->Window(), &rc);
/************************************************************/
Draw( hDC, hAttribDC, TRUE, TRUE, &rc ); hMF=CloseMetaFile(hDC);
if (NULL==hMF) return STG_E_MEDIUMFULL;
//Allocate the METAFILEPICT structure.
hMem=GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE , sizeof(METAFILEPICT));
if (NULL==hMem) { DeleteMetaFile(hMF); return E_FAIL; }
/*
* Global lock only fails in PMODE if the selector is invalid * (like it was discarded) or references a 0 length segment, * neither of which can happen here. */ pMF=(LPMETAFILEPICT)GlobalLock(hMem);
pMF->hMF=hMF; pMF->mm=MM_ANISOTROPIC;
//Insert the extents in MM_HIMETRIC units.
/********* Use the extent rect, not the window rect *********/ rc = m_RectExt; // GetClientRect(m_pCtrl->Window(), &rc);
/************************************************************/
RectConvertMappings(&rc, FALSE); pMF->xExt=rc.right; pMF->yExt=rc.bottom;
GlobalUnlock(hMem);
*phMem=hMem; return NOERROR; }
/*
* CPolyline::SendAdvise * * Purpose: * Calls the appropriate IOleClientSite or IAdviseSink member * function for various events such as closure, renaming, etc. * * Parameters: * uCode UINT OBJECTCODE_* identifying the notification. * * Return Value: * None */
void CPolyline::SendAdvise(UINT uCode) { DWORD dwAspect=DVASPECT_CONTENT | DVASPECT_THUMBNAIL;
switch (uCode) { case OBJECTCODE_SAVED: if (NULL!=m_pIOleAdviseHolder) m_pIOleAdviseHolder->SendOnSave(); break;
case OBJECTCODE_CLOSED: if (NULL!=m_pIOleAdviseHolder) m_pIOleAdviseHolder->SendOnClose();
break;
case OBJECTCODE_RENAMED: //Call IOleAdviseHolder::SendOnRename (later)
break;
case OBJECTCODE_SAVEOBJECT: if (m_fDirty && NULL!=m_pIOleClientSite) m_pIOleClientSite->SaveObject();
m_fDirty=FALSE; break;
case OBJECTCODE_DATACHANGED: m_fDirty=TRUE;
//No flags are necessary here.
if (NULL!=m_pIDataAdviseHolder) { m_pIDataAdviseHolder->SendOnDataChange(m_pImpIDataObject, 0, 0); }
if ( ( NULL!=m_pIAdviseSink ) & (dwAspect & m_dwAdviseAspects)) { m_pIAdviseSink->OnViewChange(dwAspect & m_dwAdviseAspects, 0); }
break;
case OBJECTCODE_SHOWWINDOW: if (NULL!=m_pIOleClientSite) m_pIOleClientSite->OnShowWindow(TRUE);
break;
case OBJECTCODE_HIDEWINDOW: if (NULL!=m_pIOleClientSite) m_pIOleClientSite->OnShowWindow(FALSE);
break;
case OBJECTCODE_SHOWOBJECT: if (NULL!=m_pIOleClientSite) m_pIOleClientSite->ShowObject();
break; }
return; }
/*
* CPolyline::SendEvent * * Purpose: * Send an event to all connection points. * * * Parameters: * uEventType Event Type * dwParam Parameter to send with event. * * Return Value: * None */
void CPolyline::SendEvent ( IN UINT uEventType, IN DWORD dwParam ) { INT i;
// Don't send if container has frozen events
if (m_fFreezeEvents) return;
// Pass event to each connection point
for (i=0; i<CONNECTION_POINT_CNT; i++) { m_ConnectionPoint[i].SendEvent(uEventType, dwParam); } }
/*
* CPolyline::InPlaceActivate * * Purpose: * Goes through all the steps of activating the Polyline as an * in-place object. * * Parameters: * pActiveSite LPOLECLIENTSITE of the active site we show in. * fIncludeUI BOOL controls whether we call UIActivate too. * * Return Value: * HRESULT Whatever error code is appropriate. */
HRESULT CPolyline::InPlaceActivate( LPOLECLIENTSITE pActiveSite, BOOL fIncludeUI ) { HRESULT hr; HWND hWndSite; HWND hWndHW; HWND hWndCtrl; RECT rcPos; RECT rcClip; OLEINPLACEFRAMEINFO frameInfo;
if (NULL==pActiveSite) return E_POINTER;
// If we already have a site, just handle UI
if (NULL != m_pIOleIPSite) { if (fIncludeUI) { UIActivate(); SetFocus(m_pCtrl->Window()); }
return NOERROR; }
// Initialization, obtaining interfaces, OnInPlaceActivate.
hr=pActiveSite->QueryInterface(IID_IOleInPlaceSite, (PPVOID)&m_pIOleIPSite);
if (FAILED(hr)) return hr;
hr=m_pIOleIPSite->CanInPlaceActivate();
if (NOERROR!=hr) { m_pIOleIPSite->Release(); m_pIOleIPSite=NULL; return E_FAIL; }
m_pIOleIPSite->OnInPlaceActivate();
// Get the window context and create a window.
m_pIOleIPSite->GetWindow(&hWndSite); frameInfo.cb=sizeof(OLEINPLACEFRAMEINFO);
m_pIOleIPSite->GetWindowContext(&m_pIOleIPFrame, &m_pIOleIPUIWindow, &rcPos, &rcClip, &frameInfo);
/*
* Create the hatch window after we get a parent window. We * could not create the hatch window sooner because had nothing * to use for the parent. */ m_pHW=new CHatchWin();
if (NULL==m_pHW) { InPlaceDeactivate(); return E_OUTOFMEMORY; }
if (!m_pHW->Init(hWndSite, ID_HATCHWINDOW, NULL)) { InPlaceDeactivate(); return E_OUTOFMEMORY; }
hr=m_pImpIRunnableObject->Run(NULL);
// Move the hatch window to the container window.
hWndHW = m_pHW->Window(); SetParent(hWndHW, hWndSite);
// Move the Polyline window from the hidden dialog to hatch window
hWndCtrl = m_pCtrl->Window();
m_pHW->HwndAssociateSet(hWndCtrl); m_pHW->ChildSet(hWndCtrl); m_pHW->RectsSet(&rcPos, &rcClip); //Positions polyline
ShowWindow(hWndHW, SW_SHOW); SendAdvise(OBJECTCODE_SHOWOBJECT);
// Critical for accelerators to work initially.
SetFocus(hWndCtrl);
if (fIncludeUI) hr = UIActivate(); else hr = NOERROR;
/*
* Since we don't have an Undo while in-place, tell the continer * to free it's undo state immediately. */ m_pIOleIPSite->DiscardUndoState();
return hr;
}
/*
* CPolyline::InPlaceDeactivate * * Purpose: * Reverses all the activation steps from InPlaceActivate. * * Parameters: * None * * Return Value: * None */
void CPolyline::InPlaceDeactivate(void) { UIDeactivate();
if (NULL!=m_pHW) { ShowWindow(m_pHW->Window(), SW_HIDE);
// Move the window to its foster home
if (m_pCtrl->Window()) { SetParent(m_pCtrl->Window(), g_hWndFoster); }
m_pHW->ChildSet(NULL);
delete m_pHW; m_pHW=NULL; }
ReleaseInterface(m_pIOleIPFrame); ReleaseInterface(m_pIOleIPUIWindow)
if (NULL!=m_pIOleIPSite) { m_pIOleIPSite->OnInPlaceDeactivate(); ReleaseInterface(m_pIOleIPSite); }
return; }
/*
* CPolyline::UIActivate * * Purpose: * Goes through all the steps of activating the user interface of * Polyline as an in-place object. * * Parameters: * None * * Return Value: * HRESULT NOERROR or error code. */
HRESULT CPolyline::UIActivate(void) { LPWSTR szUserType;
// If already UI active, just return
if (m_fUIActive) return NOERROR;
m_fUIActive = TRUE;
// Show hatched border only if enabled
if (m_fHatch) m_pHW->ShowHatch(TRUE);
// Call IOleInPlaceSite::UIActivate
if (NULL!=m_pIOleIPSite) m_pIOleIPSite->OnUIActivate();
// Set the active object
szUserType = ResourceString(IDS_USERTYPE);
if (NULL != m_pIOleIPFrame) m_pIOleIPFrame->SetActiveObject(m_pImpIOleIPActiveObject, szUserType);
if (NULL != m_pIOleIPUIWindow) m_pIOleIPUIWindow->SetActiveObject(m_pImpIOleIPActiveObject, szUserType);
// Negotiate border space. None needed.
if (NULL != m_pIOleIPFrame) m_pIOleIPFrame->SetBorderSpace(NULL);
if (NULL != m_pIOleIPUIWindow) m_pIOleIPUIWindow->SetBorderSpace(NULL);
// Create the shared menu. No items added.
if (NULL != m_pIOleIPFrame) m_pIOleIPFrame->SetMenu(NULL, NULL, m_pCtrl->Window());
return NOERROR; }
/*
* CPolyline::UIDeactivate * * Purpose: * Reverses all the user interface activation steps from * UIActivate. * * Parameters: * None * * Return Value: * None */
void CPolyline::UIDeactivate(void) { if (!m_fUIActive){ return; }
m_fUIActive=FALSE;
// Hide hatched border if enabled
if (m_fHatch && NULL != m_pHW ){ m_pHW->ShowHatch(FALSE); }
// Tell frame and UI Window we aren't active
if (NULL!=m_pIOleIPFrame){ m_pIOleIPFrame->SetActiveObject(NULL, NULL); }
if (NULL!=m_pIOleIPUIWindow){ m_pIOleIPUIWindow->SetActiveObject(NULL, NULL); }
//We don't have any shared menu or tools to clean up.
if (NULL!=m_pIOleIPSite){ m_pIOleIPSite->OnUIDeactivate(FALSE); } }
/*
* AmbientGet * * Purpose: * Retrieves a specific ambient property into a VARIANT. * * Parameters: * dispID DISPID of the property to retrieve. * pva VARIANT * to fill with the new value. * * Return value * BOOL TRUE if the ambient was retrieved, FALSE * otherwise. */
BOOL CPolyline::AmbientGet(DISPID dispID, VARIANT *pva) { HRESULT hr; DISPPARAMS dp;
if (NULL==pva) return FALSE;
if (NULL==m_pIDispatchAmbients) return FALSE;
SETNOPARAMS(dp); hr=m_pIDispatchAmbients->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dp, pva, NULL, NULL);
return SUCCEEDED(hr); }
/*
* AmbientsInitialize * * Purpose: * Attempts to retrieve the container's ambient properties * and initialize (or reinitialize) Polyline accordingly. * * Parameters: * dwWhich DWORD containing INITAMBIENT_... flags * describing which ambients to initialize. * This can be any combination. * * Return Value: * None */
void CPolyline::AmbientsInitialize(DWORD dwWhich) { VARIANT va; LPFONT pIFont,pIFontClone; LPFONTDISP pIFontDisp;
if (NULL == m_pIDispatchAmbients) { return; }
/*
* We need to retrieve these ambients into these variables: * * Ambient Property: Variable: * ----------------------------------------------- * DISPID_AMBIENT_SHOWHATCHING m_fHatch * DISPID_AMBIENT_UIDEAD m_fUIDead * DISPID_AMBIENT_BACKCOLOR m_pCtrl... * DISPID_AMBIENT_FONT ..... m_pCtrl... * DISPID_AMBIENT_FORECOLOR m_pCtrl... * DISPID_AMBIENT_APPEARANCE m_pCtrl... * DISPID_AMBIENT_USERMODE m_pCtrl... */
VariantInit(&va);
if ((INITAMBIENT_SHOWHATCHING & dwWhich) &&AmbientGet(DISPID_AMBIENT_SHOWHATCHING, &va)) {
m_fHatch=V_BOOL(&va);
if (NULL != m_pHW) m_pHW->ShowHatch(m_fHatch && m_fUIActive); }
if ((INITAMBIENT_UIDEAD & dwWhich) && AmbientGet(DISPID_AMBIENT_UIDEAD, &va)) {
m_pCtrl->m_fUIDead = (BOOLEAN)V_BOOL(&va); }
if ((INITAMBIENT_USERMODE & dwWhich) && AmbientGet(DISPID_AMBIENT_USERMODE, &va)) {
m_pCtrl->m_fUserMode = (BOOLEAN)V_BOOL(&va); }
if ((INITAMBIENT_APPEARANCE & dwWhich) && AmbientGet(DISPID_AMBIENT_APPEARANCE, &va)) {
m_pCtrl->put_Appearance(V_I4(&va), TRUE); }
if ((INITAMBIENT_BACKCOLOR & dwWhich) && AmbientGet(DISPID_AMBIENT_BACKCOLOR, &va)) {
m_pCtrl->put_BackPlotColor(V_I4(&va), TRUE); }
if ((INITAMBIENT_FORECOLOR & dwWhich) && AmbientGet(DISPID_AMBIENT_FORECOLOR, &va)) {
m_pCtrl->put_FgndColor(V_I4(&va), TRUE); }
if ((INITAMBIENT_FONT & dwWhich) && AmbientGet(DISPID_AMBIENT_FONT, &va)) {
pIFontDisp = (LPFONTDISP)V_DISPATCH(&va);
if (pIFontDisp != NULL) {
if (SUCCEEDED(pIFontDisp->QueryInterface(IID_IFont, (PPVOID)&pIFont))) {
if (SUCCEEDED(pIFont->Clone(&pIFontClone))) { m_pCtrl->put_Font(pIFontClone, TRUE); pIFontClone->Release(); } pIFont->Release(); }
pIFontDisp->Release(); } }
if ((INITAMBIENT_RTL & dwWhich) && AmbientGet( DISPID_AMBIENT_RIGHTTOLEFT, &va)) { m_pCtrl->m_fRTL = (BOOLEAN)V_BOOL(&va); } }
void CPolyline::Draw( HDC hDC, HDC hAttribDC, BOOL fMetafile, BOOL fEntire, LPRECT pRect) {
RECT rc;
if (!fMetafile && !RectVisible(hDC, pRect)) return;
SetMapMode(hDC, MM_ANISOTROPIC);
//
// Always set up the window extents to the natural window size
// so the drawing routines can work in their normal dev coords
//
// Use client rect vs. extent rect for Zoom calculation.
// Zoom factor = prcPos / Extent, so pRect/ClientRect.
/********* Use the extent rect, not the window rect *********/ // Using rectExt makes Word printing correct at all zoom levels.
rc = m_RectExt; // GetClientRect(m_pCtrl->Window(), &rc);
/************************************************************/
SetWindowOrgEx(hDC, 0, 0, NULL); SetWindowExtEx(hDC, rc.right, rc.bottom, NULL);
SetViewportOrgEx(hDC, pRect->left, pRect->top, NULL); SetViewportExtEx(hDC, pRect->right - pRect->left, pRect->bottom - pRect->top, NULL);
m_pCtrl->InitView( g_hWndFoster); m_pCtrl->Render(hDC, hAttribDC, fMetafile, fEntire, &rc);
return; }
|