|
|
/*++
Copyright (C) 1993-1999 Microsoft Corporation
Module Name:
ioleobj.cpp
Abstract:
Implementation of the IOleObject interface for Polyline. Some of these just pass through to the default handler which does default implementations.
--*/
#include "polyline.h"
#include "unkhlpr.h"
#include "utils.h"
#include "unihelpr.h"
void RegisterAsRunning(IUnknown *pUnk, IMoniker *pmk, DWORD dwFlags, LPDWORD pdwReg);
/*
* CImpIOleObject interface implementation */
IMPLEMENT_CONTAINED_CONSTRUCTOR(CPolyline, CImpIOleObject) IMPLEMENT_CONTAINED_DESTRUCTOR(CImpIOleObject)
IMPLEMENT_CONTAINED_QUERYINTERFACE(CImpIOleObject) IMPLEMENT_CONTAINED_ADDREF(CImpIOleObject)
STDMETHODIMP_(ULONG) CImpIOleObject::Release( void ) { --m_cRef;
#if 0
// Release cached site related interfaces
if (m_cRef == 0) { ReleaseInterface(m_pObj->m_pIOleClientSite); ReleaseInterface(m_pObj->m_pIOleControlSite); ReleaseInterface(m_pObj->m_pIDispatchAmbients); } #endif
return m_pUnkOuter->Release(); }
/*
* CImpIOleObject::SetClientSite * CImpIOleObject::GetClientSite * * Purpose: * Manages the IOleClientSite pointer of our container. */
STDMETHODIMP CImpIOleObject::SetClientSite (LPOLECLIENTSITE pIOleClientSite) { ReleaseInterface(m_pObj->m_pIOleClientSite); ReleaseInterface(m_pObj->m_pIOleControlSite); ReleaseInterface(m_pObj->m_pIDispatchAmbients);
m_pObj->m_pIOleClientSite = pIOleClientSite;
if (NULL != m_pObj->m_pIOleClientSite) { HRESULT hr; LPMONIKER pmk; LPOLECONTAINER pIOleCont;
m_pObj->m_pIOleClientSite->AddRef();
/*
* Within IRunnableObject::Run we're supposed to register * ourselves as running...however, the moniker has to come * from the container's IOleClientSite::GetMoniker. But * Run is called before SetClientSite here, so we have to * register now that we do have the client site as well * as lock the container. */
hr = m_pObj->m_pIOleClientSite->GetMoniker (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, &pmk);
if (SUCCEEDED(hr)) { RegisterAsRunning(m_pUnkOuter, pmk, 0, &m_pObj->m_dwRegROT); pmk->Release(); }
hr = m_pObj->m_pIOleClientSite->GetContainer(&pIOleCont);
if (SUCCEEDED(hr)) { m_pObj->m_fLockContainer=TRUE; pIOleCont->LockContainer(TRUE); pIOleCont->Release(); }
/*
* Go get the container's IDispatch for ambient * properties if it has one, and initilize ourself * with those properties. */ hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IDispatch , (void **)&m_pObj->m_pIDispatchAmbients);
if (SUCCEEDED(hr)) m_pObj->AmbientsInitialize((ULONG)INITAMBIENT_ALL); /*
* Get the control site */ hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IOleControlSite, (void **)&m_pObj->m_pIOleControlSite);
}
return NOERROR; }
STDMETHODIMP CImpIOleObject::GetClientSite(LPOLECLIENTSITE *ppSite) { //Be sure to AddRef the new pointer you are giving away.
*ppSite=m_pObj->m_pIOleClientSite; m_pObj->m_pIOleClientSite->AddRef();
return NOERROR; }
/*
* CImpIOleObject::SetHostNames * * Purpose: * Provides the object with names of the container application and * the object in the container to use in object user interface. * * Parameters: * pszApp LPCOLESTR of the container application. * pszObj LPCOLESTR of some name that is useful in window * titles. * * Return Value: * HRESULT NOERROR */
STDMETHODIMP CImpIOleObject::SetHostNames(LPCOLESTR /* pszApp */ , LPCOLESTR /* pszObj */) { return NOERROR; }
/*
* CImpIOleObject::Close * * Purpose: * Forces the object to close down its user interface and unload. * * Parameters: * dwSaveOption DWORD describing the circumstances under which * the object is being saved and closed. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CImpIOleObject::Close(DWORD dwSaveOption) { BOOL fSave=FALSE;
//If object is dirty and we're asked to save, save it and close.
if (OLECLOSE_SAVEIFDIRTY==dwSaveOption && m_pObj->m_fDirty) fSave=TRUE;
/*
* If asked to prompt, only do so if dirty, then if we get a * YES, save as usual and close. On NO, just close. On * CANCEL return OLE_E_PROMPTSAVECANCELLED. */ if (OLECLOSE_PROMPTSAVE==dwSaveOption && m_pObj->m_fDirty) { UINT uRet;
uRet = MessageBox(NULL, ResourceString(IDS_CLOSEPROMPT), ResourceString(IDS_CLOSECAPTION), MB_YESNOCANCEL);
if (IDCANCEL==uRet) return ResultFromScode(OLE_E_PROMPTSAVECANCELLED);
if (IDYES==uRet) fSave=TRUE; }
if (fSave) { m_pObj->SendAdvise(OBJECTCODE_SAVEOBJECT); m_pObj->SendAdvise(OBJECTCODE_SAVED); }
//We get directly here on OLECLOSE_NOSAVE.
if ( m_pObj->m_fLockContainer && ( NULL != m_pObj->m_pIOleClientSite ) ) {
//Match LockContainer call from SetClientSite
LPOLECONTAINER pIOleCont;
if (SUCCEEDED(m_pObj->m_pIOleClientSite->GetContainer(&pIOleCont))) { pIOleCont->LockContainer(FALSE); pIOleCont->Release(); } } // Deactivate
m_pObj->InPlaceDeactivate();
// Revoke registration in ROT
if (m_pObj->m_dwRegROT != 0) {
IRunningObjectTable *pROT;
if (!FAILED(GetRunningObjectTable(0, &pROT))) { pROT->Revoke(m_pObj->m_dwRegROT); pROT->Release(); m_pObj->m_dwRegROT = 0; } }
return NOERROR; }
/*
* CImpIOleObject::DoVerb * * Purpose: * Executes an object-defined action. * * Parameters: * iVerb LONG index of the verb to execute. * pMSG LPMSG describing the event causing the * activation. * pActiveSite LPOLECLIENTSITE to the site involved. * lIndex LONG the piece on which execution is happening. * hWndParent HWND of the window in which the object can play * in-place. * pRectPos LPRECT of the object in hWndParent where the * object can play in-place if desired. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CImpIOleObject::DoVerb(LONG iVerb, LPMSG /* pMSG */ , LPOLECLIENTSITE pActiveSite, LONG /* lIndex */, HWND /* hWndParent */ , LPCRECT /* pRectPos */) { HRESULT hr; CAUUID caGUID;
USES_CONVERSION
switch (iVerb) { case OLEIVERB_HIDE: if (NULL != m_pObj->m_pIOleIPSite) { m_pObj->UIDeactivate(); ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE); } else {
ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE); m_pObj->SendAdvise(OBJECTCODE_HIDEWINDOW); } break;
case OLEIVERB_PRIMARY: case OLEIVERB_SHOW: if (NULL != m_pObj->m_pIOleIPSite) { ShowWindow(m_pObj->m_pHW->Window(), SW_SHOW); return NOERROR; //Already active
}
if (m_pObj->m_fAllowInPlace) { return m_pObj->InPlaceActivate(pActiveSite ,TRUE); }
return ResultFromScode(OLEOBJ_S_INVALIDVERB); break;
case OLEIVERB_INPLACEACTIVATE: if (NULL != m_pObj->m_pHW) { HWND hWndHW=m_pObj->m_pHW->Window();
ShowWindow(hWndHW, SW_SHOW); SetFocus(hWndHW);
return NOERROR; }
/*
* Only inside-out supporting containers will use * this verb. */ m_pObj->m_fContainerKnowsInsideOut=TRUE; m_pObj->InPlaceActivate(pActiveSite, FALSE); break;
case OLEIVERB_UIACTIVATE: m_pObj->InPlaceActivate(pActiveSite, TRUE); break;
case OLEIVERB_PROPERTIES: case POLYLINEVERB_PROPERTIES:
/*
* Let the container try first if there are * extended controls. Otherwise we'll display * our own pages. */ if (NULL!=m_pObj->m_pIOleControlSite) { hr=m_pObj->m_pIOleControlSite->ShowPropertyFrame();
if (NOERROR==hr) break; //All done
}
//Put up our property pages.
hr=m_pObj->m_pImpISpecifyPP->GetPages(&caGUID);
if (FAILED(hr)) return FALSE;
hr=OleCreatePropertyFrame(m_pObj->m_pCtrl->Window(), 10, 10 , T2W(ResourceString(IDS_PROPFRM_TITLE)), 1, (IUnknown **)&m_pObj , caGUID.cElems, caGUID.pElems , LOCALE_USER_DEFAULT, 0L, NULL);
//Free the GUIDs
CoTaskMemFree((void *)caGUID.pElems); break;
default: return ResultFromScode(OLEOBJ_S_INVALIDVERB); }
return NOERROR; }
/*
* CImpIOleObject::GetUserClassID * * Purpose: * Used for linked objects, this returns the class ID of what end * users think they are editing. * * Parameters: * pClsID LPCLSID in which to store the CLSID. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CImpIOleObject::GetUserClassID(LPCLSID pClsID) { /*
* If you are not registered to handle data other than yourself, * then you can just return your class ID here. If you are * registered as usable from Treat-As dialogs, then you need to * return the CLSID of what you are really editing. */
*pClsID=CLSID_SystemMonitor; return NOERROR; }
/*
* CImpIOleObject::SetExtent * * Purpose: * Sets the size of the object in HIMETRIC units. * * Parameters: * dwAspect DWORD of the aspect affected. * pszl LPSIZEL containing the new size. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CImpIOleObject::SetExtent( DWORD dwAspect, LPSIZEL pszl ) {
RECT rectExt;
if (dwAspect == DVASPECT_CONTENT) { // convert from HIMETRIC to device coord
SetRect(&rectExt, 0, 0, pszl->cx, pszl->cy); m_pObj->RectConvertMappings(&rectExt,TRUE);
// If changed and non-zero, store as new extent
if ( !EqualRect ( &m_pObj->m_RectExt, &rectExt ) && !IsRectEmpty( &rectExt ) ) { m_pObj->m_RectExt = rectExt;
m_pObj->m_pImpIPolyline->SizeSet(&rectExt, TRUE); // Notify container of change to force metafile update
//m_pObj->SendAdvise(OBJECTCODE_DATACHANGED);
} }
return NOERROR; }
/*
* CImpIOleObject::GetExtent * * Purpose: * Retrieves the size of the object in HIMETRIC units. * * Parameters: * dwAspect DWORD of the aspect requested * pszl LPSIZEL into which to store the size. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CImpIOleObject::GetExtent(DWORD dwAspect, LPSIZEL pszl) { //Delegate directly to IViewObject2::GetExtent
return m_pObj->m_pImpIViewObject->GetExtent(dwAspect, -1 , NULL, pszl); }
/*
* CImpIOleObject::Advise * CImpIOleObject::Unadvise * CImpIOleObject::EnumAdvise * * Purpose: * Advisory connection functions. */
STDMETHODIMP CImpIOleObject::Advise( LPADVISESINK pIAdviseSink, LPDWORD pdwConn ) { if (NULL==m_pObj->m_pIOleAdviseHolder) { HRESULT hr;
hr=CreateOleAdviseHolder(&m_pObj->m_pIOleAdviseHolder);
if (FAILED(hr)) return hr; }
return m_pObj->m_pIOleAdviseHolder->Advise(pIAdviseSink, pdwConn); }
STDMETHODIMP CImpIOleObject::Unadvise(DWORD dwConn) { if (NULL!=m_pObj->m_pIOleAdviseHolder) return m_pObj->m_pIOleAdviseHolder->Unadvise(dwConn);
return ResultFromScode(E_FAIL); }
STDMETHODIMP CImpIOleObject::EnumAdvise(LPENUMSTATDATA *ppEnum) { if (NULL!=m_pObj->m_pIOleAdviseHolder) return m_pObj->m_pIOleAdviseHolder->EnumAdvise(ppEnum);
return ResultFromScode(E_FAIL); }
/*
* CImpIOleObject::SetMoniker * * Purpose: * Informs the object of its moniker or its container's moniker * depending on dwWhich. * * Parameters: * dwWhich DWORD describing whether the moniker is the * object's or the container's. * pmk LPMONIKER with the name. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CImpIOleObject::SetMoniker(DWORD /* dwWhich */ , LPMONIKER /* pmk */) { LPMONIKER pmkFull; HRESULT hr = ResultFromScode(E_FAIL); HRESULT hrTmp; LPBC pbc;
if (NULL!=m_pObj->m_pIOleClientSite) { hr = m_pObj->m_pIOleClientSite->GetMoniker (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL , &pmkFull);
if (SUCCEEDED(hr)) { hrTmp = CreateBindCtx(0,&pbc);
if (SUCCEEDED(hrTmp)) { hrTmp = pmkFull->IsRunning(pbc, NULL, NULL); pbc->Release();
if (hrTmp == NOERROR) { pmkFull->Release(); return NOERROR; } }
//This will revoke the old one if m_dwRegROT is nonzero.
RegisterAsRunning(m_pUnkOuter, pmkFull, 0, &m_pObj->m_dwRegROT);
//Inform clients of the new moniker
if (NULL!=m_pObj->m_pIOleAdviseHolder) m_pObj->m_pIOleAdviseHolder->SendOnRename(pmkFull);
pmkFull->Release(); } } return hr; }
/*
* CImpIOleObject::GetMoniker * * Purpose: * Asks the object for a moniker that can later be used to * reconnect to it. * * Parameters: * dwAssign DWORD determining how to assign the moniker to * to the object. * dwWhich DWORD describing which moniker the caller wants. * ppmk LPMONIKER * into which to store the moniker. * * Return Value: * HRESULT NOERROR or a general error value. */
STDMETHODIMP CImpIOleObject::GetMoniker(DWORD /* dwAssign */ , DWORD /* dwWhich */, LPMONIKER *ppmk) { HRESULT hr=ResultFromScode(E_FAIL);
*ppmk=NULL;
/*
* Since we only support embedded objects, our moniker * is always the full moniker from the contianer. */
if (NULL!=m_pObj->m_pIOleClientSite) { hr=m_pObj->m_pIOleClientSite->GetMoniker (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, ppmk); }
return (NULL!=*ppmk) ? NOERROR : hr; }
//Methods not implemented or trivial
STDMETHODIMP CImpIOleObject::InitFromData( LPDATAOBJECT /* pIDataObject */ , BOOL /* fCreation */, DWORD /* dw */) { return ResultFromScode(E_NOTIMPL); }
STDMETHODIMP CImpIOleObject::GetClipboardData(DWORD /* dwReserved */ , LPDATAOBJECT * /* ppIDataObj */) { return ResultFromScode(E_NOTIMPL); }
STDMETHODIMP CImpIOleObject::Update(void) { return NOERROR; }
STDMETHODIMP CImpIOleObject::IsUpToDate(void) { return NOERROR; }
STDMETHODIMP CImpIOleObject::SetColorScheme(LPLOGPALETTE /* pLP */) { return ResultFromScode(E_NOTIMPL); }
//Methods implemented using registry helper functions in OLE.
STDMETHODIMP CImpIOleObject::EnumVerbs(LPENUMOLEVERB *ppEnum) { return OleRegEnumVerbs(m_pObj->m_clsID, ppEnum); }
STDMETHODIMP CImpIOleObject::GetUserType( DWORD dwForm, LPOLESTR *ppszType ) { return OleRegGetUserType(m_pObj->m_clsID, dwForm, ppszType); }
STDMETHODIMP CImpIOleObject::GetMiscStatus( DWORD dwAspect, LPDWORD pdwStatus ) { return OleRegGetMiscStatus(m_pObj->m_clsID, dwAspect, pdwStatus); }
void RegisterAsRunning( IUnknown *pUnk, IMoniker *pmk, DWORD dwFlags, LPDWORD pdwReg ) { IRunningObjectTable *pROT; HRESULT hr; DWORD dwReg = *pdwReg;
dwReg=*pdwReg;
if (FAILED(GetRunningObjectTable(0, &pROT))) return;
hr = pROT->Register(dwFlags, pUnk, pmk, pdwReg);
if (MK_S_MONIKERALREADYREGISTERED == GetScode(hr)) { if (0 != dwReg) pROT->Revoke(dwReg); }
pROT->Release();
return; }
|