/*
* IOLEOBJ.CPP
* Polyline Component Chapter 24
*
* Implementation of the IOleObject interface for Polyline. Some of
* these just pass through to the default handler which does default
* implementations.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/
#include "polyline.h"
/*
* CImpIOleObject::CImpIOleObject
* CImpIOleObject::~CImpIOleObject
*
* Parameters (Constructor):
* pObj PCPolyline of the object we're in.
* pUnkOuter LPUNKNOWN to which we delegate.
*/
CImpIOleObject::CImpIOleObject(PCPolyline pObj
, LPUNKNOWN pUnkOuter)
{
m_cRef=0;
m_pObj=pObj;
m_pUnkOuter=pUnkOuter;
return;
}
CImpIOleObject::~CImpIOleObject(void)
{
return;
}
/*
* CImpIOleObject::QueryInterface
* CImpIOleObject::AddRef
* CImpIOleObject::Release
*
* Purpose:
* IUnknown members for CImpIOleObject object.
*/
STDMETHODIMP CImpIOleObject::QueryInterface(REFIID riid, PPVOID ppv)
{
return m_pUnkOuter->QueryInterface(riid, ppv);
}
STDMETHODIMP_(ULONG) CImpIOleObject::AddRef(void)
{
++m_cRef;
return m_pUnkOuter->AddRef();
}
STDMETHODIMP_(ULONG) CImpIOleObject::Release(void)
{
--m_cRef;
return m_pUnkOuter->Release();
}
/*
* CImpIOleObject::SetClientSite
* CImpIOleObject::GetClientSite
*
* Purpose:
* Manages the IOleClientSite pointer of our container.
*/
STDMETHODIMP CImpIOleObject::SetClientSite
(LPOLECLIENTSITE pIOleClientSite)
{
if (NULL!=m_pObj->m_pIOleClientSite)
m_pObj->m_pIOleClientSite->Release();
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))
{
INOLE_RegisterAsRunning(this, 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();
}
//CHAPTER24MOD
/*
* 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(INITAMBIENT_ALL);
//End CHAPTER24MOD
}
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)
{
if (NULL!=m_pObj->m_hDlg)
{
TCHAR szTemp[128];
#ifdef WIN32ANSI
char szObj[80];
WideCharToMultiByte(CP_ACP, 0, pszObj, -1, szObj, 80
, NULL, NULL);
wsprintf(szTemp, SZPOLYFRAMETITLE, szObj);
#else
wsprintf(szTemp, SZPOLYFRAMETITLE, pszObj);
#endif
SetWindowText(m_pObj->m_hDlg, szTemp);
}
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)
{
HWND hWnd;
BOOL fSave=FALSE;
hWnd=m_pObj->m_hDlg;
//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)
{
TCHAR szTitle[20];
TCHAR szTemp[80];
UINT uRet;
lstrcpy(szTitle, m_pObj->String(IDS_CLOSECAPTION));
lstrcpy(szTemp, m_pObj->String(IDS_CLOSEPROMPT));
uRet=MessageBox(hWnd, szTemp, szTitle, 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)
{
//Match LockContainer call from SetClientSite
LPOLECONTAINER pIOleCont;
if (SUCCEEDED(m_pObj->m_pIOleClientSite
->GetContainer(&pIOleCont)))
{
pIOleCont->LockContainer(FALSE);
pIOleCont->Release();
}
}
if (NULL!=hWnd)
{
//This hides the window and sends the appropriate notify.
DoVerb(OLEIVERB_HIDE, NULL, NULL, -1, NULL, NULL);
m_pObj->SendAdvise(OBJECTCODE_CLOSED);
PostMessage(hWnd, POLYM_CLOSE, 0, 0L);
}
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;
//CHAPTER24MOD
CAUUID caGUID;
//End CHAPTER24MOD
switch (iVerb)
{
case OLEIVERB_HIDE:
if (NULL!=m_pObj->m_pIOleIPSite)
{
if (NULL!=m_pObj->m_pHW)
ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
}
else
{
if (NULL!=m_pObj->m_hDlg)
ShowWindow(m_pObj->m_hDlg, SW_HIDE);
}
m_pObj->SendAdvise(OBJECTCODE_HIDEWINDOW);
m_pObj->m_fAllowInPlace=TRUE;
break;
case OLEIVERB_PRIMARY:
case OLEIVERB_SHOW:
if (NULL!=m_pObj->m_pIOleIPSite)
{
if (NULL!=m_pObj->m_pHW)
ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
return NOERROR; //Already active
}
if (m_pObj->m_fAllowInPlace)
{
if (SUCCEEDED(m_pObj->InPlaceActivate(pActiveSite
, TRUE)))
return NOERROR;
}
//FALL THROUGH
case OLEIVERB_OPEN:
if (NULL!=m_pObj->m_pIOleIPSite)
{
m_pObj->InPlaceDeactivate();
m_pObj->m_fAllowInPlace=FALSE;
}
/*
* If we're not running, make sure we are. In any
* case, make the dialog visible and insure it has
* the right parent now.
*/
hr=NOERROR;
if (NULL==m_pObj->m_hDlg)
hr=m_pObj->m_pImpIRunnableObject->Run(NULL);
if (FAILED(hr) || NULL==m_pObj->m_hDlg)
return ResultFromScode(E_OUTOFMEMORY);
ShowWindow(m_pObj->m_hDlg, SW_SHOW);
SetFocus(m_pObj->m_hDlg);
m_pObj->SendAdvise(OBJECTCODE_SHOWOBJECT);
m_pObj->SendAdvise(OBJECTCODE_SHOWWINDOW);
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;
//CHAPTER24MOD
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_hWnd, 10, 10
, OLETEXT("Polyline"), 1, (IUnknown **)&m_pObj
, caGUID.cElems, caGUID.pElems
, LANG_NEUTRAL, 0L, NULL);
//Free the GUIDs
CoTaskMemFree((void *)caGUID.pElems);
break;
//End CHAPTER24MOD
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_Polyline19;
return NOERROR;
}
/*
* CImpIOleObject::SetExtent
*
* Purpose:
* Sets the size of the object in HIMETRIC units. Since we're in
* a dialog, the size of the object in us is fixed, so we ignore
* this call.
*
* 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)
{
//Ignored: no size change in the dialog.
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);
if (NULL!=m_pObj->m_pIOleClientSite)
{
hr=m_pObj->m_pIOleClientSite->GetMoniker
(OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
, &pmkFull);
}
if (SUCCEEDED(hr))
{
if (NOERROR==pmkFull->IsRunning(NULL, NULL, NULL))
{
pmkFull->Release();
return NOERROR;
}
//This will revoke the old one if m_dwRegROT is nonzero.
INOLE_RegisterAsRunning(m_pObj, 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);
}