mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2301 lines
62 KiB
2301 lines
62 KiB
//+----------------------------------------------------------------------------
|
|
//
|
|
// File: ctr.cpp
|
|
//
|
|
// Module: CMDIAL32.DLL
|
|
//
|
|
// Synopsis: Implements the Ole Container object for the future splash
|
|
// Animation control.
|
|
//
|
|
// Copyright (c) 1998-1999 Microsoft Corporation
|
|
//
|
|
// Author: nickball Created 02/10/98
|
|
//
|
|
//+----------------------------------------------------------------------------
|
|
|
|
#include "cmmaster.h"
|
|
|
|
/*
|
|
#define STRICT
|
|
*/
|
|
|
|
// macros used to reduce verbiage in RECT handling.
|
|
|
|
#define WIDTH(r) (r.right - r.left)
|
|
#define HEIGHT(r) (r.bottom - r.top)
|
|
|
|
// max size for LoadString.
|
|
|
|
// string constants
|
|
const WCHAR g_awchHostName[] = L"ICM FS OC Container";
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LinkToOle32
|
|
//
|
|
// Synopsis: Initializes the specified Ole32Linkage by linking to the DLL
|
|
// specified in pszOle32 and retrieving the proc address for the
|
|
// functions that we need to call
|
|
//
|
|
// Arguments: pOle32Link - ptr to Ole32LinkagStruct
|
|
// pszOl32 - ptr DLL name string
|
|
//
|
|
// Returns: TRUE if SUCCESS
|
|
// FALSE otherwise.
|
|
//
|
|
// History: nickball Created 8/14/97
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL LinkToOle32(
|
|
Ole32LinkageStruct *pOle32Link,
|
|
LPCSTR pszOle32)
|
|
{
|
|
MYDBGASSERT(pOle32Link);
|
|
MYDBGASSERT(pszOle32);
|
|
|
|
LPCSTR apszOle32[] = {
|
|
"OleInitialize",
|
|
"OleUninitialize",
|
|
"OleSetContainedObject",
|
|
"CoCreateInstance",
|
|
NULL
|
|
};
|
|
|
|
MYDBGASSERT(sizeof(pOle32Link->apvPfnOle32)/sizeof(pOle32Link->apvPfnOle32[0])==sizeof(apszOle32)/sizeof(apszOle32[0]));
|
|
|
|
ZeroMemory(pOle32Link, sizeof(Ole32LinkageStruct));
|
|
|
|
return (LinkToDll(&pOle32Link->hInstOle32,
|
|
pszOle32,
|
|
apszOle32,
|
|
pOle32Link->apvPfnOle32));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: UnlinkFromOle32
|
|
//
|
|
// Synopsis: The reverse of LinkToOle32().
|
|
//
|
|
// Arguments: pOle32Link - ptr to Ole32LinkagStruct
|
|
//
|
|
// Returns: Nothing
|
|
//
|
|
// History: nickball Created 8/14/97
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void UnlinkFromOle32(Ole32LinkageStruct *pOle32Link)
|
|
{
|
|
MYDBGASSERT(pOle32Link);
|
|
|
|
if (pOle32Link->hInstOle32)
|
|
{
|
|
FreeLibrary(pOle32Link->hInstOle32);
|
|
}
|
|
|
|
ZeroMemory(pOle32Link, sizeof(Ole32LinkageStruct));
|
|
}
|
|
|
|
VOID CleanupCtr(LPICMOCCtr pCtr)
|
|
{
|
|
if (pCtr)
|
|
{
|
|
pCtr->ShutDown();
|
|
pCtr->Release();
|
|
}
|
|
}
|
|
|
|
|
|
// move (translate) the rectangle by (dx, dy)
|
|
inline VOID MoveRect(LPRECT prc, int dx, int dy)
|
|
{
|
|
prc->left += dx;
|
|
prc->right += dx;
|
|
prc->top += dy;
|
|
prc->bottom += dy;
|
|
}
|
|
|
|
const ULONG MAX_STATUS_TEXT = MAX_PATH;
|
|
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::CDynamicOleAut
|
|
//
|
|
// Synopsis: ctor for the Dynamic OleAut class
|
|
//
|
|
// Arguments: None
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CDynamicOleAut::CDynamicOleAut()
|
|
{
|
|
//
|
|
// Setup OLEAUT32 linkage
|
|
//
|
|
|
|
LPCSTR apszOleAut[] = {
|
|
"VariantClear",
|
|
"VariantCopy",
|
|
"VariantInit",
|
|
"VariantChangeType",
|
|
"SysAllocString",
|
|
"SysFreeString",
|
|
NULL
|
|
};
|
|
|
|
MYDBGASSERT(sizeof(m_OleAutLink.apvPfnOleAut)/sizeof(m_OleAutLink.apvPfnOleAut[0]) ==
|
|
sizeof(apszOleAut)/sizeof(apszOleAut[0]));
|
|
|
|
ZeroMemory(&m_OleAutLink, sizeof(m_OleAutLink));
|
|
|
|
//
|
|
// Do the link, but make it obvious if it fails
|
|
//
|
|
|
|
if (!LinkToDll(&m_OleAutLink.hInstOleAut, "OLEAUT32.DLL",
|
|
apszOleAut, m_OleAutLink.apvPfnOleAut))
|
|
{
|
|
if (m_OleAutLink.hInstOleAut)
|
|
{
|
|
FreeLibrary(m_OleAutLink.hInstOleAut);
|
|
}
|
|
ZeroMemory(&m_OleAutLink, sizeof(m_OleAutLink));
|
|
}
|
|
|
|
MYDBGASSERT(m_OleAutLink.hInstOleAut);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::~CDynamicOleAut
|
|
//
|
|
// Synopsis: dtor for the Dynamic OleAut class
|
|
//
|
|
// Arguments: None
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CDynamicOleAut::~CDynamicOleAut()
|
|
{
|
|
if (m_OleAutLink.hInstOleAut)
|
|
{
|
|
FreeLibrary(m_OleAutLink.hInstOleAut);
|
|
}
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::DynVariantClear
|
|
//
|
|
// Synopsis: Wrapper for VariantClear in OLEAUT32.DLL
|
|
//
|
|
// Arguments: See OLEAUT32.DLL documentation
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CDynamicOleAut::DynVariantClear(VARIANTARG FAR* pVar)
|
|
{
|
|
if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnVariantClear)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return m_OleAutLink.pfnVariantClear(pVar);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::DynVariantCopy
|
|
//
|
|
// Synopsis: Wrapper for VariantCopy in OLEAUT32.DLL
|
|
//
|
|
// Arguments: See OLEAUT32.DLL documentation
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CDynamicOleAut::DynVariantCopy(
|
|
VARIANTARG FAR* pVar1,
|
|
VARIANTARG FAR* pVar2)
|
|
{
|
|
if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnVariantCopy)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return m_OleAutLink.pfnVariantCopy(pVar1, pVar2);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::DynVariantInit
|
|
//
|
|
// Synopsis: Wrapper for VariantInit in OLEAUT32.DLL
|
|
//
|
|
// Arguments: See OLEAUT32.DLL documentation
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
CDynamicOleAut::DynVariantInit(VARIANTARG FAR* pVar)
|
|
{
|
|
if (m_OleAutLink.hInstOleAut && m_OleAutLink.pfnVariantInit)
|
|
{
|
|
m_OleAutLink.pfnVariantInit(pVar);
|
|
}
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::DynVariantChangeType
|
|
//
|
|
// Synopsis: Wrapper for VariantChangeType in OLEAUT32.DLL
|
|
//
|
|
// Arguments: See OLEAUT32.DLL documentation
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
CDynamicOleAut::DynVariantChangeType(
|
|
VARIANTARG FAR* pVar1,
|
|
VARIANTARG FAR* pVar2,
|
|
unsigned short wFlags,
|
|
VARTYPE vt)
|
|
{
|
|
if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnVariantChangeType)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
return m_OleAutLink.pfnVariantChangeType(pVar1, pVar2, wFlags, vt);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::DynSysAllocString
|
|
//
|
|
// Synopsis: Wrapper for SysAllocString in OLEAUT32.DLL
|
|
//
|
|
// Arguments: See OLEAUT32.DLL documentation
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BSTR
|
|
CDynamicOleAut::DynSysAllocString(OLECHAR FAR* sz)
|
|
{
|
|
if (NULL == m_OleAutLink.hInstOleAut || NULL == m_OleAutLink.pfnSysAllocString)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return m_OleAutLink.pfnSysAllocString(sz);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::DynSysFreeString
|
|
//
|
|
// Synopsis: Wrapper for SysFreeString in OLEAUT32.DLL
|
|
//
|
|
// Arguments: See OLEAUT32.DLL documentation
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
CDynamicOleAut::DynSysFreeString(BSTR bstr)
|
|
{
|
|
if (m_OleAutLink.hInstOleAut && m_OleAutLink.pfnSysFreeString)
|
|
{
|
|
m_OleAutLink.pfnSysFreeString(bstr);
|
|
}
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CDynamicOleAut::Initialized
|
|
//
|
|
// Synopsis: Simple query to report if linkage is valid
|
|
//
|
|
// Arguments: None
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CDynamicOleAut::Initialized()
|
|
{
|
|
return (NULL != m_OleAutLink.hInstOleAut);
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::CICMOCCtr
|
|
//
|
|
// Synopsis: ctor for the OLE Controls container class.
|
|
//
|
|
// Arguments: [hWnd] -- hWnd for the main browser
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#pragma warning(disable:4355) // this used in initialization list
|
|
CICMOCCtr::CICMOCCtr(const HWND hWndMainDlg, const HWND hWndFrame) :
|
|
m_hWndMainDlg(hWndMainDlg),
|
|
m_hWndFrame(hWndFrame),
|
|
m_CS(this),
|
|
m_AS(this),
|
|
m_IPF(this),
|
|
m_IPS(this),
|
|
m_OCtr(this),
|
|
m_PB(this),
|
|
m_pActiveObj(0),
|
|
m_Ref(1),
|
|
m_pUnk(0),
|
|
m_pOC(0),
|
|
m_pVO(0),
|
|
m_pOO(0),
|
|
m_pIPO(0),
|
|
m_pDisp(0),
|
|
m_state(OS_PASSIVE),
|
|
m_dwMiscStatus(0),
|
|
m_fModelessEnabled(TRUE)
|
|
{
|
|
::memset(&m_rcToolSpace, 0, sizeof m_rcToolSpace);
|
|
InitPixelsPerInch(); // initialize the HIMETRIC routines
|
|
|
|
// init all the state mappings to -1
|
|
for (INT i = PS_Interactive; i < PS_Last; i++)
|
|
{
|
|
m_alStateMappings[i] = -1;
|
|
}
|
|
}
|
|
#pragma warning(default:4355)
|
|
|
|
CICMOCCtr::~CICMOCCtr(VOID)
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::HasLinkage
|
|
//
|
|
// Synopsis: Initialize - verify that we have a link to OLEAUT32.DLL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CICMOCCtr::Initialized(VOID)
|
|
{
|
|
return m_DOA.Initialized();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::ShutDown
|
|
//
|
|
// Synopsis: cleanup all the OLE stuff.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CICMOCCtr::ShutDown(VOID)
|
|
{
|
|
if (m_pOC)
|
|
m_pOC->Release();
|
|
if (m_pIPO)
|
|
{
|
|
MYDBGASSERT(m_state == OS_UIACTIVE || m_state == OS_INPLACE);
|
|
if (m_state == OS_UIACTIVE)
|
|
{
|
|
m_pIPO->UIDeactivate();
|
|
// m_state = OS_INPLACE; // for documentation purposes
|
|
if (m_pActiveObj)
|
|
{
|
|
m_pActiveObj->Release();
|
|
m_pActiveObj = 0;
|
|
}
|
|
}
|
|
|
|
m_pIPO->InPlaceDeactivate();
|
|
// m_state = OS_RUNNING;
|
|
}
|
|
if (m_pVO)
|
|
{
|
|
// kill the advisory connection
|
|
m_pVO->SetAdvise(DVASPECT_CONTENT, 0, 0);
|
|
m_pVO->Release();
|
|
}
|
|
if (m_pOO)
|
|
{
|
|
m_pOO->Close(OLECLOSE_NOSAVE);
|
|
m_pOO->SetClientSite(0);
|
|
m_pOO->Release();
|
|
}
|
|
if (m_pDisp)
|
|
m_pDisp->Release();
|
|
if (m_pUnk)
|
|
m_pUnk->Release();
|
|
|
|
MYDBGASSERT(!m_pActiveObj);
|
|
|
|
m_pDisp = 0;
|
|
m_pOC = 0;
|
|
m_pIPO = 0;
|
|
m_pActiveObj = 0;
|
|
m_pVO = 0;
|
|
m_pOO = 0;
|
|
m_pUnk = 0;
|
|
m_state = OS_PASSIVE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::AddRef
|
|
//
|
|
// Synopsis: bump refcount up on container. Note that all the
|
|
// interfaces handed out delegate to this one.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CICMOCCtr::AddRef(VOID)
|
|
{
|
|
return ++m_Ref;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::Release
|
|
//
|
|
// Synopsis: decrement the refcount on container, and delete when it
|
|
// hits 0 - note that all the interfaces handed out delegate
|
|
// to this one.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG)
|
|
CICMOCCtr::Release(VOID)
|
|
{
|
|
ULONG ulRC = --m_Ref;
|
|
|
|
if (!ulRC)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return ulRC;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::QueryInterface
|
|
//
|
|
// Synopsis: this is where we hand out all the interfaces. All the
|
|
// interfaces delegate back to this.
|
|
//
|
|
// Arguments: [riid] -- IID of interface desired.
|
|
// [ppv] -- interface returned.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CICMOCCtr::QueryInterface(REFIID riid, LPVOID FAR * ppv)
|
|
{
|
|
*ppv = 0;
|
|
|
|
LPUNKNOWN pUnk;
|
|
|
|
if (::IsEqualIID(riid, IID_IOleClientSite))
|
|
pUnk = &m_CS;
|
|
else if (::IsEqualIID(riid, IID_IAdviseSink))
|
|
pUnk = &m_AS;
|
|
else if (::IsEqualIID(riid, IID_IUnknown))
|
|
pUnk = this;
|
|
else if (::IsEqualIID(riid, IID_IOleInPlaceFrame) ||
|
|
::IsEqualIID(riid, IID_IOleInPlaceUIWindow))
|
|
pUnk = &m_IPF;
|
|
else if (::IsEqualIID(riid, IID_IOleInPlaceSite))
|
|
pUnk = &m_IPS;
|
|
else if (::IsEqualIID(riid, IID_IPropertyBag))
|
|
pUnk = &m_PB;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
pUnk->AddRef();
|
|
|
|
*ppv = pUnk;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
extern "C" CLSID const CLSID_FS =
|
|
{
|
|
0xD27CDB6E,
|
|
0xAE6D,
|
|
0x11CF,
|
|
{ 0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 }
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::CreateFSOC
|
|
//
|
|
// Synopsis: Creates an instance of the Future Splash OC, embedding it in
|
|
// our container. QIs for all the relevant pointers and
|
|
// transitions the control to the UIActive state.
|
|
//
|
|
// Arguments: pOle32Link - ptr to Ole32LinkageStruct containing funtion
|
|
// pointers to dynamically linked OLE32 DLL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CICMOCCtr::CreateFSOC(Ole32LinkageStruct *pOle32Link)
|
|
{
|
|
MYDBGASSERT(pOle32Link);
|
|
|
|
HRESULT hr = -1;
|
|
RECT rc;
|
|
LPPERSISTPROPERTYBAG pPPB = 0;
|
|
|
|
// GetFrameWindow() also asserts that hwnd ::IsWindow()
|
|
MYDBGASSERT(GetFrameWindow());
|
|
|
|
//
|
|
// Use dyna-linked CoCreateInstance to create the OC
|
|
//
|
|
|
|
if (pOle32Link->hInstOle32 && pOle32Link->pfnCoCreateInstance)
|
|
{
|
|
hr = pOle32Link->pfnCoCreateInstance(
|
|
CLSID_FS,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IUnknown,
|
|
(LPVOID *) &m_pUnk);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
m_state = OS_RUNNING;
|
|
|
|
// get the View object - although we rarely draw the OC thru this.
|
|
// since we immediately transition it to the UIActive state, it
|
|
// usually draws itself through its own wndproc.
|
|
hr = m_pUnk->QueryInterface(IID_IViewObject, (LPVOID FAR *) &m_pVO);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// get the IOleObject pointer - the main interface through which
|
|
// we handle the basic OLE object state transition stuff
|
|
// for the Future Splash OC
|
|
hr = m_pUnk->QueryInterface(IID_IOleObject, (LPVOID FAR *) &m_pOO);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// get status bits on the OC - we're not currently doing anything
|
|
// with them.
|
|
hr = m_pOO->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// set our client site into the oleobject
|
|
hr = m_pOO->SetClientSite(&m_CS);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
hr = m_pUnk->QueryInterface(IID_IPersistPropertyBag, (LPVOID *) &pPPB);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
hr = pPPB->Load(&m_PB, 0);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// set our advise sink into the view object, so we
|
|
// get notifications that we need to redraw.
|
|
hr = m_pVO->SetAdvise(DVASPECT_CONTENT, 0, &m_AS);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
//
|
|
// Use dyna-linked OleSetContainedObject
|
|
//
|
|
|
|
if (pOle32Link->hInstOle32 && pOle32Link->pfnOleSetContainedObject)
|
|
{
|
|
// standard OLE protocol stuff.
|
|
hr = pOle32Link->pfnOleSetContainedObject(m_pUnk, TRUE);
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// ditto
|
|
hr = m_pOO->SetHostNames(g_awchHostName, 0);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// get the IDispatch for the control. This is for late-bound
|
|
// access to the properties and methods.
|
|
hr = m_pUnk->QueryInterface(IID_IDispatch, (LPVOID FAR *) &m_pDisp);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// get the IOleControl interface; although we use it for very little.
|
|
hr = m_pUnk->QueryInterface(IID_IOleControl, (LPVOID FAR *) &m_pOC);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// transition the control to the inplace-active state - it will have
|
|
// an hWnd after it returns from DoVerb, and will begin drawing
|
|
// itself.
|
|
|
|
_GetDoVerbRect(&rc); // get rect for firing verbs.
|
|
|
|
hr = m_pOO->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, &m_CS, 0, GetMainWindow(), &rc);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
// go ahead and UI activate it. This will cause it to QI for our
|
|
// IOleInPlaceFrame and call SetActiveObject, which we will store
|
|
// in m_pActiveObj
|
|
hr = m_pOO->DoVerb(OLEIVERB_UIACTIVATE, 0, &m_CS, 0, GetMainWindow(), &rc);
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
Cleanup:
|
|
if (pPPB)
|
|
pPPB->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::_AdjustForTools
|
|
//
|
|
// Synopsis: adjusts the rect passed in for any toolspace claimed by the
|
|
// FS OC. Currently, the FS OC always just
|
|
// passed in a rect with four zeros in it - but if it ever
|
|
// does decide to do this, we're ready :).
|
|
//
|
|
// Arguments: [prc] -- the rect we want to reduce by the BORDERWIDTHS
|
|
// stored in m_rcToolSpace.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CICMOCCtr::_AdjustForTools(LPRECT prc)
|
|
{
|
|
prc->left += m_rcToolSpace.left;
|
|
prc->top += m_rcToolSpace.top;
|
|
prc->bottom -= m_rcToolSpace.bottom;
|
|
prc->right -= m_rcToolSpace.right;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::GetSize
|
|
//
|
|
// Synopsis: returns the size, in pixels, of the FS OC.
|
|
//
|
|
// Arguments: [prc] -- returned size.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CICMOCCtr::GetSize(LPRECT prc)
|
|
{
|
|
MYDBGASSERT(m_pOO);
|
|
HRESULT hr;
|
|
|
|
// if we're inplace active, just ask the frame window.
|
|
if (m_state >= OS_INPLACE)
|
|
{
|
|
MYDBGASSERT(m_pIPO);
|
|
::GetClientRect(GetFrameWindow(), prc);
|
|
hr = S_OK;
|
|
}
|
|
else // not inplace active - probably this is never hit.
|
|
{
|
|
SIZEL sizel;
|
|
hr = m_pOO->GetExtent(DVASPECT_CONTENT, &sizel);
|
|
if (!hr)
|
|
{
|
|
prc->left = 0;
|
|
prc->top = 0;
|
|
prc->right = ::HPixFromHimetric(sizel.cx);
|
|
prc->bottom = ::VPixFromHimetric(sizel.cy);
|
|
}
|
|
}
|
|
|
|
// adjust the borders for any tools that a UIActive object
|
|
// wants to place there.
|
|
if (!hr)
|
|
_AdjustForTools(prc);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::DoLayout
|
|
//
|
|
// Synopsis: manages the vertical layout of things -
|
|
// sizes the OC container itself.
|
|
//
|
|
// Arguments: [cxMain] -- width
|
|
// [cyMain] -- height
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CICMOCCtr::DoLayout(INT cxMain, INT cyMain)
|
|
{
|
|
RECT rc;
|
|
|
|
MYDBGASSERT(m_hWndFrame && ::IsWindow(m_hWndFrame));
|
|
|
|
::GetClientRect(m_hWndFrame, &rc);
|
|
|
|
SetSize(&rc, TRUE);
|
|
}
|
|
|
|
HRESULT
|
|
CICMOCCtr::_SetExtent(LPRECT prc)
|
|
{
|
|
SIZEL sizel;
|
|
HRESULT hr;
|
|
|
|
sizel.cx = ::HimetricFromHPix(prc->right - prc->left);
|
|
sizel.cy = ::HimetricFromVPix(prc->bottom - prc->top);
|
|
|
|
MYDBGASSERT(m_pOO);
|
|
|
|
hr = m_pOO->SetExtent(DVASPECT_CONTENT, &sizel);
|
|
if (hr)
|
|
goto cleanup;
|
|
|
|
hr = m_pOO->GetExtent(DVASPECT_CONTENT, &sizel);
|
|
if (hr)
|
|
goto cleanup;
|
|
|
|
prc->right = ::HPixFromHimetric(sizel.cx);
|
|
prc->bottom = ::VPixFromHimetric(sizel.cy);
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::SetSize
|
|
//
|
|
// Synopsis: sets the size of the FS OC space (the HTML area)
|
|
//
|
|
// Effects: if fMoveFrameWindow is TRUE, then it moves the whole
|
|
// framewindow around, otherwise, it just readjusts how much
|
|
// of the framewindow space is used by the OC itself.
|
|
// In reality, what happens is that the OC calls us to
|
|
// set some border space (although at this writing it still
|
|
// is setting BORDERWIDTHS of 0,0,0,0), we allow that
|
|
// much space, then call IOleInPlaceObject->SetObjectRects
|
|
// to resize the object to whatever's left.
|
|
// Otherwise, if the object is not yet active, we just
|
|
// call IOleObject::SetExtent().
|
|
//
|
|
// Arguments: [prc] -- size to set object to
|
|
// [fMoveFrameWindow] -- is the hwnd size changing, or just
|
|
// the object within?
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CICMOCCtr::SetSize(LPRECT prc, BOOL fMoveFrameWindow)
|
|
{
|
|
HRESULT hr;
|
|
RECT rcClient;
|
|
RECT rcExtent;
|
|
|
|
// get client coords.
|
|
rcClient = *prc;
|
|
::MoveRect(&rcClient, -rcClient.left, -rcClient.top);
|
|
|
|
if (fMoveFrameWindow)
|
|
{
|
|
::SetWindowPos(
|
|
GetFrameWindow(),
|
|
0,
|
|
prc->left,
|
|
prc->top,
|
|
prc->right - prc->left,
|
|
prc->bottom - prc->top,
|
|
SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
if (m_pActiveObj)
|
|
m_pActiveObj->ResizeBorder(&rcClient, &m_IPF, TRUE);
|
|
}
|
|
|
|
// subtract off any tools the client has around .
|
|
_AdjustForTools(&rcClient);
|
|
|
|
rcExtent = rcClient;
|
|
hr = _SetExtent(&rcExtent);
|
|
if (hr)
|
|
goto cleanup;
|
|
|
|
// now we need to call SetObjectRects
|
|
if (m_pIPO && m_state >= OS_INPLACE)
|
|
hr = m_pIPO->SetObjectRects(&rcExtent, &rcClient);
|
|
|
|
cleanup:
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::Paint
|
|
//
|
|
// Synopsis: Paint with no parameters
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CICMOCCtr::Paint(VOID)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
RECT rc;
|
|
|
|
// we don't need to call IViewObject if the object is activated.
|
|
// it's got an hWnd and is receiving paint messages of its own.
|
|
if (m_state < OS_INPLACE)
|
|
{
|
|
if (!GetSize(&rc))
|
|
{
|
|
::BeginPaint(GetFrameWindow(), &ps);
|
|
Paint(ps.hdc, &rc);
|
|
::EndPaint(GetFrameWindow(), &ps);
|
|
}
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::Paint
|
|
//
|
|
// Synopsis: paint with the hdc and rect passed in. Uses
|
|
// IViewObject::Draw()
|
|
//
|
|
// Arguments: [hDC] -- dc to draw to - can be container's or
|
|
// even print dc (never is a print dc in
|
|
// our scenario -
|
|
// [lpr] -- rect for painting.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CICMOCCtr::Paint(HDC hDC, LPRECT lpr)
|
|
{
|
|
// adjust the borders in to allow for any tools the OC
|
|
// wanted to insert - so far it never does.
|
|
_AdjustForTools(lpr);
|
|
|
|
// have to use a RECTL instead of RECT - remnant of the
|
|
// OLE 16 bit days.
|
|
RECTL rcl = {lpr->left, lpr->top, lpr->right, lpr->bottom};
|
|
if (m_pVO)
|
|
m_pVO->Draw(DVASPECT_CONTENT, -1, 0, 0, 0, hDC, &rcl, 0, 0, 0);
|
|
}
|
|
|
|
|
|
VOID
|
|
CICMOCCtr::MapStateToFrame(ProgState ps)
|
|
{
|
|
// if the statemappings are -1, they are unitialized, don't use them.
|
|
LONG lFrame = m_alStateMappings[ps];
|
|
if (-1 != lFrame)
|
|
SetFrame(lFrame); // ignore error - nothing we can do.
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CICMOCCtr::SetFrame(LONG lFrame)
|
|
{
|
|
HRESULT hr;
|
|
OLECHAR * pFrameNum = OLESTR("FrameNum");
|
|
OLECHAR * pPlay = OLESTR("Play");
|
|
DISPPARAMS dp = {0, 0, 0, 0};
|
|
DISPID dispidPut = DISPID_PROPERTYPUT;
|
|
VARIANTARG var;
|
|
EXCEPINFO ei;
|
|
DISPID id;
|
|
UINT uArgErr;
|
|
|
|
m_DOA.DynVariantInit(&var);
|
|
|
|
V_VT(&var) = VT_I4;
|
|
V_I4(&var) = lFrame;
|
|
|
|
dp.cArgs = 1;
|
|
dp.rgvarg = &var;
|
|
dp.cNamedArgs = 1;
|
|
dp.rgdispidNamedArgs = &dispidPut;
|
|
|
|
hr = m_pDisp->GetIDsOfNames(
|
|
IID_NULL,
|
|
&pFrameNum,
|
|
1,
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
&id);
|
|
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
hr = m_pDisp->Invoke(
|
|
id,
|
|
IID_NULL,
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_PROPERTYPUT,
|
|
&dp,
|
|
0,
|
|
&ei,
|
|
&uArgErr);
|
|
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
hr = m_pDisp->GetIDsOfNames(
|
|
IID_NULL,
|
|
&pPlay,
|
|
1,
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
&id);
|
|
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
::memset(&dp, 0, sizeof dp);
|
|
|
|
hr = m_pDisp->Invoke(
|
|
id,
|
|
IID_NULL,
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_METHOD,
|
|
&dp,
|
|
0,
|
|
&ei,
|
|
&uArgErr);
|
|
|
|
if (hr)
|
|
goto Cleanup;
|
|
|
|
Cleanup:
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::OnActivateApp
|
|
//
|
|
// Synopsis: all WM_ACTIVATE messages (forwarded from
|
|
// main browser hWnd wndproc) must call
|
|
// IOleInPlaceActiveObject::OnFrameWindowActivate(),
|
|
// per the OLE compound document spec.
|
|
//
|
|
// Arguments: [wParam] -- whatever the WM_ACTIVATE msg passed
|
|
// [lParam] -- ditto
|
|
//
|
|
// Returns: 0 - to say we handled the message.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
LRESULT
|
|
CICMOCCtr::OnActivateApp(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (m_pActiveObj)
|
|
m_pActiveObj->OnFrameWindowActivate((BOOL)wParam);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::SetFocus
|
|
//
|
|
// Synopsis: transfers focus from framewindow to the current
|
|
// in-place active object. Per OLE Compound Document spec.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
LRESULT
|
|
CICMOCCtr::SetFocus(VOID)
|
|
{
|
|
HWND hWnd = NULL;
|
|
LPOLEINPLACEACTIVEOBJECT pAO = GetIPAObject();
|
|
|
|
if (pAO)
|
|
{
|
|
if (!pAO->GetWindow(&hWnd))
|
|
{
|
|
if (hWnd && !::IsWindow(hWnd))
|
|
hWnd = NULL;
|
|
}
|
|
}
|
|
|
|
// if no inplaceactive object, set focus to frame window.
|
|
if (!hWnd)
|
|
hWnd = GetFrameWindow();
|
|
|
|
::SetFocus(hWnd);
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CAdviseSink implementations
|
|
//
|
|
// Purpose: to implement IAdviseSink for CICMOCCtr
|
|
//
|
|
// Notes: we don't do much with this interface - it's required
|
|
// for contractual reasons only.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CAdviseSink::QueryInterface(REFIID riid, LPVOID FAR * ppv)
|
|
{
|
|
return m_pCtr->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CAdviseSink::AddRef(VOID)
|
|
{
|
|
return m_pCtr->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CAdviseSink::Release(VOID)
|
|
{
|
|
return m_pCtr->Release();
|
|
}
|
|
|
|
CAdviseSink::CAdviseSink(LPICMOCCtr pCtr) : m_pCtr(pCtr)
|
|
{
|
|
}
|
|
|
|
STDMETHODIMP_(VOID)
|
|
CAdviseSink::OnDataChange(LPFORMATETC pFEIn, LPSTGMEDIUM pSTM)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CAdviseSink::OnViewChange
|
|
//
|
|
// Synopsis: IAdviseSink::OnViewChange() - we do get called with this
|
|
// occasionally, but it appears that we're better off just
|
|
// letting the control's wndproc paint it.
|
|
// Calling this was causing extra flicker.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP_(VOID)
|
|
CAdviseSink::OnViewChange(DWORD dwAspect, LONG lIndex)
|
|
{
|
|
return;
|
|
}
|
|
|
|
STDMETHODIMP_(VOID)
|
|
CAdviseSink::OnRename(LPMONIKER pmk)
|
|
{
|
|
|
|
}
|
|
|
|
STDMETHODIMP_(VOID)
|
|
CAdviseSink::OnSave(VOID)
|
|
{
|
|
|
|
}
|
|
|
|
STDMETHODIMP_(VOID)
|
|
CAdviseSink::OnClose(VOID)
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: COleClientSite ()
|
|
//
|
|
// Purpose: our implementation of IOleClientSite
|
|
//
|
|
// Interface: COleClientSite -- ctor
|
|
// QueryInterface -- gimme an interface!
|
|
// AddRef -- bump up refcount
|
|
// Release -- bump down refcount
|
|
// SaveObject -- returns E_FAIL
|
|
// GetMoniker -- E_NOTIMPL
|
|
// GetContainer -- returns our COleContainer impl
|
|
// ShowObject -- just say OK
|
|
// OnShowWindow -- just say OK
|
|
// RequestNewObjectLayout -- E_NOTIMPL
|
|
//
|
|
// Notes: probably the most important thing our IOleClientSite
|
|
// implementation does is hand off our IOleContainer
|
|
// implementation when GetContainer() is called.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
COleClientSite::COleClientSite(LPICMOCCtr pCtr) : m_pCtr(pCtr)
|
|
{
|
|
}
|
|
|
|
STDMETHODIMP
|
|
COleClientSite::QueryInterface(REFIID riid, LPVOID FAR * ppv)
|
|
{
|
|
return m_pCtr->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
COleClientSite::AddRef(VOID)
|
|
{
|
|
return m_pCtr->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
COleClientSite::Release(VOID)
|
|
{
|
|
return m_pCtr->Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COleClientSite::SaveObject
|
|
//
|
|
// Synopsis: not implemented - makes no sense in this scenario.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
COleClientSite::SaveObject(VOID)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COleClientSite::GetMoniker
|
|
//
|
|
// Synopsis: Not yet implemented; never will be implemented.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
COleClientSite::GetMoniker(DWORD dwAssign, DWORD dwWhich, LPMONIKER FAR * ppmk)
|
|
{
|
|
*ppmk = 0;
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COleClientSite::GetContainer
|
|
//
|
|
// Synopsis: returns our implementation of IOleContainer. For some
|
|
// reason, unless we do this, frames don't work. Note that
|
|
// our IOleContainer implementation is stubbed out with
|
|
// E_NOTIMPL (it seems kind of odd to implement this for
|
|
// a container with one embedding). But it turns out the
|
|
// FS OC has a bug in it's error handling - it
|
|
// QIs for IOleContainer, then QIs from that for
|
|
// IQueryService. In truth, we'll hand out our implementation
|
|
// of IQueryService, from any interface - we're easy :).
|
|
// We *want* to provide every service the OC asks for.
|
|
// Anyway, when it can't get IOleContainer, the OC's failure
|
|
// path seems to be constructed in such a way that frames
|
|
// don't work thereafter.
|
|
//
|
|
// Arguments: [ppCtr] -- returned IOleContainer
|
|
//
|
|
// Returns: S_OK. Never fails.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
COleClientSite::GetContainer(LPOLECONTAINER FAR * ppCtr)
|
|
{
|
|
*ppCtr = &m_pCtr->m_OCtr;
|
|
(*ppCtr)->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COleClientSite::ShowObject
|
|
//
|
|
// Synopsis: IOleClientSite::ShowObject implementation. To quote the docs:
|
|
// "Tells the container to position the object so it is visible
|
|
// to the user. This method ensures that the container itself
|
|
// is visible and not minimized."
|
|
//
|
|
// In short, we ignore it. We're not going to un-minimize
|
|
// the container on the embeddings' whim :).
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
COleClientSite::ShowObject(VOID)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COleClientSite::OnShowWindow
|
|
//
|
|
// Synopsis: fine with us, return S_OK.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
COleClientSite::OnShowWindow(BOOL bShow)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: COleClientSite::RequestNewObjectLayout
|
|
//
|
|
// Synopsis: not being called by WebBrower OC, so do not implement.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
COleClientSite::RequestNewObjectLayout(VOID)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::CInPlaceFrame
|
|
//
|
|
// Synopsis: inits m_pCtr - pointer to MSNOCCtr
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CInPlaceFrame::CInPlaceFrame(LPICMOCCtr pCtr) : m_pCtr(pCtr)
|
|
{
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CInPlaceFrame::QueryInterface(REFIID riid, LPVOID FAR * ppv)
|
|
{
|
|
return m_pCtr->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CInPlaceFrame::AddRef(VOID)
|
|
{
|
|
return m_pCtr->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CInPlaceFrame::Release(VOID)
|
|
{
|
|
return m_pCtr->Release();
|
|
}
|
|
|
|
// IOleWindow stuff
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::GetWindow
|
|
//
|
|
// Synopsis: returns frame window
|
|
//
|
|
// Arguments: [phwnd] -- place to return window
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::GetWindow(HWND * phwnd)
|
|
{
|
|
MYDBGASSERT(phwnd);
|
|
|
|
// this can never fail if we've gotten this far.
|
|
*phwnd = m_pCtr->GetFrameWindow();
|
|
MYDBGASSERT(*phwnd);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::ContextSensitiveHelp
|
|
//
|
|
// Synopsis: This is not implemented by design - this is for
|
|
// the SHift+F1 context sensitive help mode and Esc
|
|
// to exit. Esc is already being used in the main
|
|
// accelerator table to mean 'stop browsing' to be
|
|
// like IE3. We do not do help this way.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::ContextSensitiveHelp(BOOL fEnterMode)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IOleInPlaceUIWindow stuff
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::GetBorder
|
|
//
|
|
// Synopsis: IOleInPlaceFrame::GetBorder() - let's us restrict where
|
|
// the server can put tools. We don't care, they can put
|
|
// them anywhere.
|
|
//
|
|
// Arguments: [lprectBorder] -- return border info in here.
|
|
//
|
|
// Returns: S_OK always with entire frame client rect -
|
|
// we place no restrictions.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::GetBorder(LPRECT lprectBorder)
|
|
{
|
|
// we have no restrictions about where the server can put tools.
|
|
::GetClientRect(m_pCtr->GetFrameWindow(), lprectBorder);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::RequestBorderSpace
|
|
//
|
|
// Synopsis: IOleInPlaceFrame::RequestBorderSpace()
|
|
// inplace object actually requests border space - if
|
|
// we can satisfy the request, we return S_OK, otherwise
|
|
// INPLACE_E_NOTOOLSPACE. It doesn't actually use the
|
|
// borderspace until it calls
|
|
// IOleInPlaceFrame::SetBorderSpace(). This is used for
|
|
// negotiation.
|
|
//
|
|
// Arguments: [pborderwidths] -- structure (actually a RECT) that is
|
|
// interpreted differently from a RECT.
|
|
// The left.top.bottom.right members
|
|
// represent space on each of our four
|
|
// borders the server would like to use.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
|
|
{
|
|
RECT rc;
|
|
RECT rcBorder;
|
|
|
|
if (!pborderwidths)
|
|
return S_OK; // they're telling us no toolspace necessary.
|
|
|
|
rcBorder = *pborderwidths;
|
|
|
|
if (GetBorder(&rc))
|
|
return INPLACE_E_NOTOOLSPACE;
|
|
|
|
if (rcBorder.left + rcBorder.right > WIDTH(rc) ||
|
|
rcBorder.top + rcBorder.bottom > HEIGHT(rc))
|
|
return INPLACE_E_NOTOOLSPACE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::SetBorderSpace
|
|
//
|
|
// Synopsis: Sets border space for tools - for some reason, the
|
|
// FS OC always calls this with a pborderwidths
|
|
// consisting of four zeros - it never actually uses any
|
|
// border space (sigh). Well, the code is here for this
|
|
// to work. We do a SetSize() to relayout stuff when
|
|
// it does this.
|
|
//
|
|
// Arguments: [pborderwidths] -- space the OC wants to use.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::SetBorderSpace(LPCBORDERWIDTHS pborderwidths)
|
|
{
|
|
RECT rc;
|
|
|
|
if (!pborderwidths)
|
|
{
|
|
::memset(&m_pCtr->m_rcToolSpace, 0, sizeof m_pCtr->m_rcToolSpace);
|
|
return S_OK;
|
|
}
|
|
|
|
if (RequestBorderSpace(pborderwidths))
|
|
return OLE_E_INVALIDRECT;
|
|
|
|
// we get the entire client space to pass to setSize().
|
|
::GetClientRect(m_pCtr->GetFrameWindow(), &rc);
|
|
m_pCtr->m_rcToolSpace = *pborderwidths;
|
|
|
|
return m_pCtr->SetSize(&rc, FALSE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::SetActiveObject
|
|
//
|
|
// Synopsis: IOleInPlaceFrame::SetActiveObject(). The server calls
|
|
// this normally whenever it transitions to the UIActive
|
|
// state. There can only be one UIActive object at a time.
|
|
// This UIACtive object is represented by its
|
|
// IOleInPlaceActiveObject implementation. We call this
|
|
// object's implementation of TranslateAccelerator() right
|
|
// in the main message loop to give the current embedding
|
|
// first shot at keyboard messages.
|
|
//
|
|
// Normally, this is only called when the container transitions
|
|
// an object to UIActive by calling
|
|
// IOleObject::DoVerb(OLEIVERB_UIACTIVE) for the object,
|
|
// transitioning all the other objects (we don't have any :))
|
|
// to OS_INPLACE (if they're OLEMISC_ACTIVATEWHENVISIBLE is set)
|
|
// or even just OS_RUNNING.
|
|
//
|
|
// Effects: sets a new active object in m_pActiveObj. Releases the
|
|
// old one, if any.
|
|
//
|
|
// Arguments: [pActiveObject] -- new active object
|
|
// [pszObjName] -- name of object - we don't use this.
|
|
//
|
|
// Returns: S_OK always.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::SetActiveObject(
|
|
IOleInPlaceActiveObject * pActiveObject,
|
|
LPCOLESTR pszObjName)
|
|
{
|
|
// reset the toolspace rect in case the last inplacactive object
|
|
// forgot to.
|
|
m_pCtr->_ResetToolSpace();
|
|
|
|
// if it was already set, save it so we can release
|
|
// it. We don't want to release it before we addref
|
|
// the new one in case they're the same thing.
|
|
LPOLEINPLACEACTIVEOBJECT pOld = m_pCtr->m_pActiveObj;
|
|
|
|
m_pCtr->m_pActiveObj = pActiveObject;
|
|
if (pActiveObject)
|
|
{
|
|
MYDBGASSERT(OS_UIACTIVE == m_pCtr->GetState());
|
|
m_pCtr->m_pActiveObj->AddRef();
|
|
}
|
|
|
|
if (pOld)
|
|
pOld->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// IOleInPlaceFrame stuff
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::InsertMenus
|
|
//
|
|
// Synopsis: OC calling us when it wants to do menu negotiation
|
|
// It calls us with a blank hmenu that we're supposed to
|
|
// add items to and fille out the OLEMENUGROUPWIDTHS
|
|
// structure to let it know what we did.
|
|
// We're not adding items to it currently.
|
|
//
|
|
// Arguments: [hmenuShared] -- menu to append to
|
|
// [pMGW] -- OLEMENUGROUPWIDTHS struct to fill out.
|
|
//
|
|
// Returns: S_OK
|
|
//
|
|
//
|
|
// Note: OC doesn't call this.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS pMGW)
|
|
{
|
|
// we're not inserting anything of our own to this menu.
|
|
pMGW->width[0] = 0; // 'File' menu
|
|
pMGW->width[2] = 0; // 'View' menu
|
|
pMGW->width[4] = 0; // 'Window' menu
|
|
pMGW->width[5] = 0; // 'Help' menu
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::SetMenu
|
|
//
|
|
// Synopsis: This is the OC calling the container asking us to
|
|
// set the shared menu in its frame. We're supposed to
|
|
// use the HOLEMENU object passed in and the
|
|
// hWndActiveObject to call OleSetMenuDescriptor() so
|
|
// that OLE can do message filtering and route WM_COMMAND
|
|
// messages.
|
|
//
|
|
//
|
|
// Arguments: [hmenuShared] -- shared menu.
|
|
// [holemenu] -- ole menu descriptor thingy
|
|
// [hwndActiveObject] -- hwnd of server who's merging menus
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
|
|
{
|
|
// we're not doing any menu negotiation
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::RemoveMenus
|
|
//
|
|
// Synopsis: IOleInPlaceFrame::RemoveMenus(), this is where the
|
|
// server gives us a chance to remove all our items from
|
|
// the hMenu. We're not adding any, so we don't remove any.
|
|
//
|
|
// Arguments: [hmenuShared] -- menu to clean up.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::RemoveMenus(HMENU hmenuShared)
|
|
{
|
|
// we aren't adding anything to this thing anyway.
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::SetStatusText
|
|
//
|
|
// Synopsis: called by the FS OC to put text in our status
|
|
// text area.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
// Arguments: [pszStatusText] -- text to display
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::SetStatusText(LPCOLESTR pszStatusText)
|
|
{
|
|
return m_pCtr->_DisplayStatusText(pszStatusText);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::_DisplayStatusText
|
|
//
|
|
// Synopsis: helper that displays status text.
|
|
//
|
|
// Arguments: [pszStatusText] -- text to display
|
|
//
|
|
//
|
|
// Returns: S_OK or HRESULT_FROM_WIN32(::GetLastError());
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CICMOCCtr::_DisplayStatusText(LPCOLESTR pszStatusText)
|
|
{
|
|
CHAR ach[MAX_STATUS_TEXT];
|
|
|
|
if (::WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pszStatusText,
|
|
-1,
|
|
ach,
|
|
NElems(ach),
|
|
0,
|
|
0))
|
|
{
|
|
// put the status text somewhere.
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
return HRESULT_FROM_WIN32(::GetLastError());
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::EnableModeless
|
|
//
|
|
// Synopsis: this is called by the embedding to let us know it's
|
|
// putting up a modal dialog box - we should 'grey' out
|
|
// any of our modeless dialogs. It delegates to
|
|
// CICMOCCtr::EnableModeless()
|
|
//
|
|
// Arguments: [fEnable] -- enable or disable.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::EnableModeless(BOOL fEnable)
|
|
{
|
|
return m_pCtr->EnableModeless(fEnable);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::EnableModeless
|
|
//
|
|
// Synopsis: delegated to from CInPlaceFrame::EnableModeless().
|
|
// always returns S_OK - we don't have any modeless
|
|
// dialogs (yet).
|
|
//
|
|
// Arguments: [fEnable] -- enable or disable.
|
|
//
|
|
// Returns: S_OK
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CICMOCCtr::EnableModeless(BOOL fEnable)
|
|
{
|
|
m_fModelessEnabled = fEnable; // in case anyone wants to know.
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceFrame::TranslateAccelerator
|
|
//
|
|
// Synopsis: The current active object's
|
|
// IOleInPlaceActiveObject::TranslateAccelerator() is being
|
|
// called at the top of our main message loop. If it
|
|
// does *not* want to handle a message, it will call
|
|
// this method of ours to pass the keyboard message back to
|
|
// us. We call ::TranslateAccelerator on the global main
|
|
// haccel, and, if it's handled (by returning TRUE - 1),
|
|
// we indicate it's handled by returning S_OK (0 :).
|
|
// On the other hand, if it's *not* handled, we return
|
|
// S_FALSE.
|
|
//
|
|
// Arguments: [lpmsg] -- keyboard msg to handle
|
|
// [wID] -- command identifier value - per spec.
|
|
//
|
|
// Returns: HRESULT
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceFrame::TranslateAccelerator(LPMSG lpmsg, WORD wID)
|
|
{
|
|
// note this should never be called - only local servers
|
|
// (out of process) should call this by using
|
|
// OleTranslateAccelerator().
|
|
return m_pCtr->_TransAccelerator(lpmsg, wID);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::_TransAccelerator
|
|
//
|
|
// Synopsis: handle accelerator messages coming from
|
|
// either IOleInplaceFrame::TranslateAccelerator, or
|
|
// IOleControlSite::TranslateAccelerator.
|
|
//
|
|
// Effects: forwards them to the main accelerator table.
|
|
//
|
|
// Arguments: [lpmsg] -- keyboard msg.
|
|
// [wID] -- per spec.
|
|
//
|
|
// Returns: S_OK if we handled it, S_FALSE otherwise.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CICMOCCtr::_TransAccelerator(LPMSG lpmsg, WORD wID)
|
|
{
|
|
// the docs suggest that this method might need to return E_INVALIDARG.
|
|
// anyway, this is defensive. If the FS OC
|
|
// calls us with an 0 ptr, we just return error
|
|
if (!lpmsg)
|
|
return E_INVALIDARG;
|
|
|
|
// forward the keystroke to the main accelerator table, if you have one.
|
|
// if you handle it, say S_OK.
|
|
|
|
#if 0
|
|
// this sample has no main accelerator table.
|
|
if (::TranslateAccelerator(GetMainWindow(),GetMainAccel(), lpmsg))
|
|
{
|
|
return S_OK; // we handled it
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
return S_FALSE; // we didn't.
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CInPlaceSite ()
|
|
//
|
|
// Purpose: IOleInPlaceSite implementation.
|
|
//
|
|
// Interface: CInPlaceSite -- ctor
|
|
// QueryInterface -- get a new interface
|
|
// AddRef -- bump ref count
|
|
// Release -- decrement ref count
|
|
// GetWindow -- returns frame window
|
|
// ContextSensitiveHelp -- not implemented by design
|
|
// CanInPlaceActivate -- returns S_OK.
|
|
// OnInPlaceActivate -- caches IOleInPlaceObject ptr
|
|
// OnUIActivate -- returns S_OK - sets state
|
|
// GetWindowContext -- returns IOleInPlaceFrame,
|
|
// IOleInPlaceUIWindow,
|
|
// PosRect and ClipRect
|
|
// Scroll -- not implemented ever
|
|
// OnUIDeactivate -- kills objmenu
|
|
// OnInPlaceDeactivate -- releases cached IOleInPlaceObject
|
|
// DiscardUndoState -- returns S_OK
|
|
// DeactivateAndUndo -- deactivates in place active object
|
|
// OnPosRectChange -- never implemented.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CInPlaceSite::CInPlaceSite(LPICMOCCtr pCtr) : m_pCtr(pCtr)
|
|
{
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CInPlaceSite::QueryInterface(REFIID riid, LPVOID FAR * ppv)
|
|
{
|
|
return m_pCtr->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CInPlaceSite::AddRef(VOID)
|
|
{
|
|
return m_pCtr->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CInPlaceSite::Release(VOID)
|
|
{
|
|
return m_pCtr->Release();
|
|
}
|
|
|
|
CPropertyBag::CPropertyBag(LPICMOCCtr pCtr) : m_pCtr(pCtr)
|
|
{
|
|
|
|
}
|
|
|
|
CPropertyBag::~CPropertyBag(VOID)
|
|
{
|
|
for (INT i = 0; i < m_aryBagProps.Size(); i++)
|
|
{
|
|
m_pCtr->m_DOA.DynSysFreeString(m_aryBagProps[i].bstrName);
|
|
m_pCtr->m_DOA.DynVariantClear(&m_aryBagProps[i].varValue);
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CPropertyBag::QueryInterface(REFIID riid, LPVOID FAR * ppv)
|
|
{
|
|
return m_pCtr->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CPropertyBag::AddRef(VOID)
|
|
{
|
|
return m_pCtr->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CPropertyBag::Release(VOID)
|
|
{
|
|
return m_pCtr->Release();
|
|
}
|
|
|
|
|
|
static LONG
|
|
LongFromValue(LPTSTR sz)
|
|
{
|
|
if (CmIsDigit(sz))
|
|
return CmAtol(sz);
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CPropertyBag::AddPropertyToBag(LPTSTR szName, LPTSTR szValue)
|
|
{
|
|
BagProp bp;
|
|
HRESULT hr;
|
|
LONG lValue;
|
|
LPWSTR pawch;
|
|
//WCHAR awch[INTERNET_MAX_URL_LENGTH] = {0};
|
|
|
|
// initialize so error cleanup can work properly.
|
|
bp.bstrName = 0;
|
|
|
|
m_pCtr->m_DOA.DynVariantInit(&bp.varValue);
|
|
|
|
if (!(pawch = (LPWSTR)CmMalloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR))))
|
|
{
|
|
goto MemoryError;
|
|
}
|
|
|
|
//if (-1 == ::mbstowcs(awch, szName, NElems(awch)))
|
|
#ifndef UNICODE
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szName, -1, pawch, INTERNET_MAX_URL_LENGTH)) // NElems(awch)))
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
#else
|
|
lstrcpyU(pawch, szName);
|
|
#endif
|
|
|
|
bp.bstrName = m_pCtr->m_DOA.DynSysAllocString(pawch);
|
|
|
|
if (!bp.bstrName)
|
|
goto MemoryError;
|
|
|
|
// see if it's a VT_I4.
|
|
lValue = ::LongFromValue(szValue);
|
|
|
|
// it's a VT_BSTR - probably most common case
|
|
if (-1 == lValue)
|
|
{
|
|
//if (-1 == ::mbstowcs(awch, szValue, NElems(awch)))
|
|
#ifndef UNICODE
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szValue, -1, pawch, INTERNET_MAX_URL_LENGTH)) // NElems(awch)))
|
|
{
|
|
hr = E_FAIL;
|
|
goto Error;
|
|
}
|
|
#else
|
|
lstrcpyU(pawch, szValue);
|
|
#endif
|
|
|
|
V_VT(&bp.varValue) = VT_BSTR;
|
|
|
|
V_BSTR(&bp.varValue) = m_pCtr->m_DOA.DynSysAllocString(pawch);
|
|
|
|
if (!V_BSTR(&bp.varValue))
|
|
goto MemoryError;
|
|
}
|
|
else // it's a VT_I4
|
|
{
|
|
V_VT(&bp.varValue) = VT_I4;
|
|
V_I4(&bp.varValue) = lValue;
|
|
}
|
|
|
|
hr = m_aryBagProps.AppendIndirect(&bp);
|
|
if (hr)
|
|
goto Error;
|
|
|
|
Cleanup:
|
|
if (pawch)
|
|
{
|
|
CmFree(pawch);
|
|
}
|
|
return hr;
|
|
|
|
MemoryError:
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
Error:
|
|
if (bp.bstrName)
|
|
m_pCtr->m_DOA.DynSysFreeString(bp.bstrName);
|
|
|
|
if (pawch)
|
|
{
|
|
CmFree(pawch);
|
|
}
|
|
|
|
m_pCtr->m_DOA.DynVariantClear(&bp.varValue);
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CPropertyBag::Read(LPCOLESTR pszName, LPVARIANT pVar, LPERRORLOG pErrorLog)
|
|
{
|
|
for (INT i = 0; i < m_aryBagProps.Size(); i++)
|
|
{
|
|
if (!::lstrcmpiU(m_aryBagProps[i].bstrName, pszName))
|
|
{
|
|
if (V_VT(pVar) == V_VT(&m_aryBagProps[i].varValue))
|
|
{
|
|
return m_pCtr->m_DOA.DynVariantCopy(pVar, &m_aryBagProps[i].varValue);
|
|
}
|
|
else
|
|
{
|
|
return m_pCtr->m_DOA.DynVariantChangeType(
|
|
pVar,
|
|
&m_aryBagProps[i].varValue,
|
|
0,
|
|
V_VT(pVar));
|
|
}
|
|
}
|
|
}
|
|
return E_INVALIDARG; // we don't have the property.
|
|
}
|
|
|
|
|
|
// IOleWindow stuff
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::GetWindow
|
|
//
|
|
// Synopsis: returns frame window.
|
|
//
|
|
// Arguments: [phwnd] -- return window *here*
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::GetWindow(HWND * phwnd)
|
|
{
|
|
// just reuse the CInPlaceFrame impl
|
|
return m_pCtr->m_IPF.GetWindow(phwnd);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::ContextSensitiveHelp
|
|
//
|
|
// Synopsis: This is not implemented by design - this is for
|
|
// the SHift+F1 context sensitive help mode and Esc
|
|
// to exit. Esc is already being used in the main
|
|
// accelerator table to mean 'stop browsing' to be
|
|
// like IE3. We do not do help this way.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::ContextSensitiveHelp(BOOL fEnterMode)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
// IOleInPlaceSite stuff
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::CanInPlaceActivate
|
|
//
|
|
// Synopsis: just say yes.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::CanInPlaceActivate(VOID)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::OnInPlaceActivate
|
|
//
|
|
// Synopsis: caches the IOleInPlaceObject pointer.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::OnInPlaceActivate(VOID)
|
|
{
|
|
HRESULT hr = m_pCtr->m_pOO->QueryInterface(
|
|
IID_IOleInPlaceObject,
|
|
(LPVOID *) &m_pCtr->m_pIPO);
|
|
|
|
if (!hr)
|
|
m_pCtr->SetState(OS_INPLACE);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::OnUIActivate
|
|
//
|
|
// Synopsis: just sets state bit
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::OnUIActivate(VOID)
|
|
{
|
|
m_pCtr->SetState(OS_UIACTIVE);
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::GetWindowContext
|
|
//
|
|
// Synopsis: returns a bunch of interfaces and positioning interface
|
|
// the inplace-active object needs to do its thang.
|
|
//
|
|
// Arguments: [ppFrame] -- return our IOleInPlaceFrame implementation
|
|
// [ppDoc] -- return our IOleInPlaceUIWindow impl.
|
|
// [prcPosRect] -- position info
|
|
// [prcClipRect] -- clip info - same as pos info for this case
|
|
// [pFrameInfo] -- return 0 - inproc object doesn't use this.
|
|
//
|
|
// Notes: note that ppFrame and ppDoc are really just the same
|
|
// object because we're an SDI app.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::GetWindowContext(
|
|
IOleInPlaceFrame **ppFrame,
|
|
IOleInPlaceUIWindow **ppDoc,
|
|
LPRECT prcPosRect,
|
|
LPRECT prcClipRect,
|
|
LPOLEINPLACEFRAMEINFO pFrameInfo)
|
|
{
|
|
// get the frame
|
|
HRESULT hr = m_pCtr->QueryInterface(
|
|
IID_IOleInPlaceFrame,
|
|
(LPVOID *)ppFrame);
|
|
|
|
MYDBGASSERT(!hr);
|
|
|
|
// return the frame again :) - this is all per-spec.
|
|
hr = m_pCtr->QueryInterface(
|
|
IID_IOleInPlaceUIWindow,
|
|
(LPVOID *) ppDoc);
|
|
|
|
MYDBGASSERT(!hr);
|
|
|
|
// get the clip and pos rect - same for this application.
|
|
HWND hWnd = m_pCtr->GetMainWindow();
|
|
MYDBGASSERT(hWnd);
|
|
HWND hWndFrame = m_pCtr->GetFrameWindow();
|
|
|
|
::GetClientRect(hWndFrame, prcPosRect);
|
|
|
|
//
|
|
// NTRAID - #148143
|
|
// Apparently the W9x implementation is different, so MapWindowPoints for
|
|
// the clipping and position rect only on 9X. Also, make sure that the
|
|
// origin is NULL to keep post 2.0 versions of future splash happy on 9X.
|
|
//
|
|
|
|
if (OS_W9X)
|
|
{
|
|
::MapWindowPoints(hWndFrame, hWnd, (LPPOINT)prcPosRect, 2);
|
|
prcPosRect->top = 0;
|
|
prcPosRect->left = 0;
|
|
}
|
|
|
|
*prcClipRect = *prcPosRect;
|
|
|
|
//
|
|
// OLYMPUS - #156880
|
|
// Clipping handled differently by future splash versions > 2.0
|
|
// so don't re-map the rect points, just use the client rect so we
|
|
// work with all splash versions - nickball
|
|
//
|
|
|
|
//::MapWindowPoints(hWndFrame, hWnd, (LPPOINT)prcClipRect, 2);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::Scroll
|
|
//
|
|
// Synopsis: never implement this for FS OC. This has
|
|
// nothing to do with the scrollbars you see on the HTML.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::Scroll(SIZE scrollExtent)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::OnUIDeactivate
|
|
//
|
|
// Synopsis: set state bits
|
|
//
|
|
// Arguments: [fUndoable] -- not used
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::OnUIDeactivate(BOOL fUndoable)
|
|
{
|
|
m_pCtr->SetState(OS_INPLACE);
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::OnInPlaceDeactivate
|
|
//
|
|
// Synopsis: releases the IOleInPlaceObject pointer we were
|
|
// caching for the object, and sets state to OS_RUNNING.
|
|
// Also fires the OLEIVERB_DISCARDUNDOSTATE at the control
|
|
// to tell it to release any undo state it's holding onto.
|
|
// I very much doubt the FS OC has any undo state,
|
|
// but, this is the protocol.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::OnInPlaceDeactivate(VOID)
|
|
{
|
|
RECT rc;
|
|
|
|
if (m_pCtr->m_pIPO)
|
|
{
|
|
m_pCtr->m_pIPO->Release();
|
|
m_pCtr->SetState(OS_RUNNING);
|
|
m_pCtr->m_pIPO = 0;
|
|
}
|
|
|
|
if (m_pCtr->m_pOO)
|
|
{
|
|
m_pCtr->_GetDoVerbRect(&rc); // get rect for firing verbs.
|
|
m_pCtr->m_pOO->DoVerb(
|
|
OLEIVERB_DISCARDUNDOSTATE,
|
|
0,
|
|
&m_pCtr->m_CS,
|
|
0,
|
|
m_pCtr->GetFrameWindow(),
|
|
0);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CICMOCCtr::_GetDoVerbRect
|
|
//
|
|
// Synopsis: whenever firing DoVerb(), we need a rect for the object
|
|
// that describes the area for the object in parent client coords.
|
|
//
|
|
// Arguments: [prc] -- rect returned.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
VOID
|
|
CICMOCCtr::_GetDoVerbRect(LPRECT prc)
|
|
{
|
|
::GetClientRect(GetFrameWindow(), prc);
|
|
::MapWindowPoints(GetFrameWindow(), GetMainWindow(), (LPPOINT)prc, 2);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::DiscardUndoState
|
|
//
|
|
// Synopsis: just say OK - we don't hold any undo state for
|
|
// object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::DiscardUndoState(VOID)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::DeactivateAndUndo
|
|
//
|
|
// Synopsis: absolutely minimum implementation of deactivateandundo.
|
|
// just calls IOleInPlaceObject::InPlaceDeactivate().
|
|
//
|
|
// Returns: S_OK always.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::DeactivateAndUndo(VOID)
|
|
{
|
|
if (m_pCtr->m_pIPO)
|
|
m_pCtr->m_pIPO->InPlaceDeactivate();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CInPlaceSite::OnPosRectChange
|
|
//
|
|
// Synopsis: never implement this.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
CInPlaceSite::OnPosRectChange(LPCRECT lprcPosRect)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: COleContainer ()
|
|
//
|
|
// Purpose: our implementation of IOleContainer. does nothing.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP
|
|
COleContainer::QueryInterface(REFIID riid, LPVOID FAR * ppv)
|
|
{
|
|
return m_pCtr->QueryInterface(riid, ppv);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
COleContainer::AddRef(VOID)
|
|
{
|
|
return m_pCtr->AddRef();
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
COleContainer::Release(VOID)
|
|
{
|
|
return m_pCtr->Release();
|
|
}
|
|
|
|
COleContainer::COleContainer(LPICMOCCtr pCtr) : m_pCtr(pCtr)
|
|
{
|
|
|
|
}
|
|
|
|
STDMETHODIMP
|
|
COleContainer::EnumObjects(DWORD grfFlags, IEnumUnknown **ppenum)
|
|
{
|
|
MYDBGASSERT(FALSE); // never called
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
COleContainer::LockContainer(BOOL fLock)
|
|
{
|
|
MYDBGASSERT(FALSE); // never called
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
COleContainer::ParseDisplayName(
|
|
IBindCtx *pbc,
|
|
LPOLESTR pszDisplayName,
|
|
ULONG *pchEaten,
|
|
IMoniker **ppmkOut)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
|