1265 lines
30 KiB
C++
1265 lines
30 KiB
C++
/*++
|
|
|
|
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"
|
|
|
|
/*
|
|
* 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 ),
|
|
m_pImpIPolyline ( NULL ),
|
|
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);
|
|
ReleaseInterface(m_pITypeLib);
|
|
|
|
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);
|
|
DeleteInterfaceImp(m_pImpIPolyline);
|
|
|
|
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;
|
|
|
|
m_pImpIPolyline=new CImpIPolyline(this, pIUnknown);
|
|
|
|
if (NULL==m_pImpIPolyline)
|
|
return FALSE;
|
|
|
|
m_pImpIConnPtCont=new CImpIConnPtCont(this, pIUnknown);
|
|
|
|
if (NULL==m_pImpIConnPtCont)
|
|
return FALSE;
|
|
|
|
for (i=0; i<CONNECTION_POINT_CNT; i++) {
|
|
m_ConnectionPoint[i].Init(this, pIUnknown, i);
|
|
}
|
|
|
|
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--;
|
|
m_pImpIPolyline->New();
|
|
|
|
/*
|
|
* Go load our own type information and save its ITypeLib
|
|
* pointer that will be used be CImpIDispatch and
|
|
* CImpIProvideClassInfo.
|
|
*/
|
|
|
|
hr=LoadRegTypeLib(LIBID_SystemMonitor, SMONCTRL_MAJ_VERSION, SMONCTRL_MIN_VERSION
|
|
, LANG_NEUTRAL, &m_pITypeLib);
|
|
|
|
if (FAILED(hr))
|
|
hr=LoadTypeLib(OLESTR("SYSMON.TLB"), &m_pITypeLib);
|
|
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
|
|
//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)
|
|
{
|
|
*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;
|
|
|
|
//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;
|
|
}
|
|
|
|
if (NULL!=*ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
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 = POLYLINE_E_INVALIDPOINTER;
|
|
} 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 POLYLINE_E_INVALIDPOINTER;
|
|
|
|
//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;
|
|
|
|
USES_CONVERSION
|
|
|
|
// 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 = T2W(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();
|
|
}
|
|
}
|
|
}
|
|
|