CTLHOST.CPP

////////////////////////////////////////////////////////////////////////// 
//
// controlhost.cpp
//
// This file contains the implementation of the CControlHost class.
// This class is used to host ActiveX Controls.
//
// (C) Copyright 1997 by Microsoft Corporation. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////

#define INITGUID
#include <exdispid.h>
#include <olectl.h>
#include "dactl.h"
#include "ctlhost.h"
#include <comdef.h>

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::CControlHost [CONSTRUCTOR]
//
CControlHost::CControlHost(IUnknown *pUnk)
:_hwnd(NULL), _punkOuter(NULL),
_cRef(0), _punk(NULL), _pvc(NULL),
_dwTBSink(0)
{
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::~CControlHost [DESTRUCTOR]
//
CControlHost::~CControlHost()
{
DeleteControl(); // insurance
}


//////////////////////////////////////////////////////////////////////////
//
//
//
HRESULT CControlHost::SetHwnd(HWND hwnd)
{
_hwnd = hwnd;
if (!GetClientRect(_hwnd, &_rcPos))
SetRectEmpty(&_rcPos);

return S_OK;
}
//////////////////////////////////////////////////////////////////////////
//
// CControlHost::QueryInterface [IUnknown]
//
HRESULT CControlHost::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
if (ppvObj == NULL)
return E_INVALIDARG;

*ppvObj = NULL;

if (IsEqualIID(riid, IID_IOleInPlaceSite))
*ppvObj = (IOleInPlaceSite *)this;
else if (IsEqualIID(riid, IID_IOleControlSite))
*ppvObj = (IOleControlSite *)this;
else if (IsEqualIID(riid, IID_IOleInPlaceSiteWindowless))
*ppvObj = (IOleInPlaceSiteWindowless *)this;
else if (IsEqualIID(riid, IID_IDispatch))
*ppvObj = (IDispatch *)this;
else
return (E_NOINTERFACE);

if(*ppvObj)
AddRef();

return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::AddRef [IUnknown]
//
ULONG CControlHost::AddRef()
{
return (_cRef++);
}

ULONG CControlHost::Release()
{
_cRef--;

if (_cRef > 0)
return (_cRef);

_cRef = 0;
delete this;

return (0);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::SaveObject [IOleClientSite]
//
HRESULT CControlHost::SaveObject()
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetMoniker [IOleClientSite]
//
HRESULT CControlHost::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER * ppMk)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetContainer [IOleClientSite]
//
HRESULT CControlHost::GetContainer(LPOLECONTAINER * ppContainer )
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::ShowObject [IOleClientSite]
//
HRESULT CControlHost::ShowObject()
{
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnShowWindow [IOleClientSite]
//
HRESULT CControlHost::OnShowWindow(BOOL fShow)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::RequestNewObjectLayout [IOleClientSite]
//
HRESULT CControlHost::RequestNewObjectLayout()
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetWindow [IOleWindow]
//
HRESULT CControlHost::GetWindow(HWND * lphwnd)
{
if (_hwnd == NULL)
return (S_FALSE);

*lphwnd = _hwnd;
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::ContextSensitiveHelp [IOleWindow]
//
HRESULT CControlHost::ContextSensitiveHelp(BOOL fEnterMode)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::CanInPlaceActivate [IOleInPlaceSite]
//
HRESULT CControlHost::CanInPlaceActivate(void)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnInPlaceActivate [IOleInPlaceSite]
//
HRESULT CControlHost::OnInPlaceActivate(void)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnUIActivate [IOleInPlaceSite]
//
HRESULT CControlHost::OnUIActivate(void)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetWindowContext [IOleInPlaceSite]
//
HRESULT CControlHost::GetWindowContext (IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppIIPUIWin,
LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
*ppFrame = this;
AddRef();

*ppIIPUIWin = NULL;

CopyRect(lprcPosRect, &_rcPos);
CopyRect(lprcClipRect, &_rcPos);

lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
lpFrameInfo->fMDIApp = FALSE;
lpFrameInfo->hwndFrame = _hwnd;
lpFrameInfo->haccel = 0;
lpFrameInfo->cAccelEntries = 0;

return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::Scroll [IOleInPlaceSite]
//
HRESULT CControlHost::Scroll(SIZE scrollExtent)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnUIDeactivate [IOleInPlaceSite]
//
HRESULT CControlHost::OnUIDeactivate(BOOL fUndoable)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnInPlaceDeactivate [IOleInPlaceSite]
//
HRESULT CControlHost::OnInPlaceDeactivate(void)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::DiscardUndoState [IOleInPlaceSite]
//
HRESULT CControlHost::DiscardUndoState(void)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::DeactivateAndUndo [IOleInPlaceSite]
//
HRESULT CControlHost::DeactivateAndUndo(void)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnPosRectChange [IOleInPlaceSite]
//
HRESULT CControlHost::OnPosRectChange(LPCRECT lprcPosRect)
{
RECT rcPos, rcClient;
HWND hwnd;
GetWindow(&hwnd);
GetClientRect(hwnd, &rcClient);
GetWindowRect(hwnd, &rcPos);

if(rcClient.bottom < lprcPosRect->bottom)
rcPos.bottom += lprcPosRect->bottom - rcClient.bottom;
else
rcPos.bottom -= rcClient.bottom - lprcPosRect->bottom;

if(rcClient.right < lprcPosRect->right)
rcPos.right += lprcPosRect->right - rcClient.right;
else
rcPos.right -= rcClient.right - lprcPosRect->right;

MoveWindow( hwnd,
rcPos.left,
rcPos.top,
rcPos.right - rcPos.left,
rcPos.bottom - rcPos.top,
TRUE);

return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnInPlaceActivateEx [IOleInPlaceSiteEx]
//
HRESULT CControlHost::OnInPlaceActivateEx(BOOL *pfNoRedraw, DWORD dwFlags)
{
OleLockRunning(_punk, TRUE, FALSE);
HRESULT hr = E_FAIL;

return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnInPlaceDeactivateEx [IOleInPlaceSiteEx]
//
HRESULT CControlHost::OnInPlaceDeactivateEx(BOOL fNoRedraw)
{
OleLockRunning(_punk, FALSE, FALSE);
return S_OK;
}


//////////////////////////////////////////////////////////////////////////
//
// CControlHost::RequestUIActivate [IOleInPlaceSiteEx]
//
HRESULT CControlHost::RequestUIActivate(void)
{
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::CanWindowlessActivate [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::CanWindowlessActivate(void)
{
return (TRUE); // m_bCanWindowlessActivate);
}
//////////////////////////////////////////////////////////////////////////
// [IOleInPlaceSiteWindowless]
// CControlHost::GetCapture
//
HRESULT CControlHost::GetCapture(void)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::SetCapture [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::SetCapture(BOOL fCapture)
{

if (fCapture)
{
::SetCapture(_hwnd);
_bCapture = TRUE;
}
else
{
::ReleaseCapture();
_bCapture = FALSE;
}
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetFocus [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::GetFocus(void)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::SetFocus [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::SetFocus(BOOL fFocus)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetDC [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::GetDC(LPCRECT pRect, DWORD grfFlags, HDC *phDC)
{
if (!phDC)
return E_POINTER;

*phDC = ::GetDC(_hwnd);
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::ReleaseDC [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::ReleaseDC(HDC hDC)
{
::ReleaseDC(_hwnd, hDC);
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::InvalidateRect [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::InvalidateRect(LPCRECT pRect, BOOL fErase)
{
::InvalidateRect(_hwnd, pRect, fErase);
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::InvalidateRgn [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::InvalidateRgn(HRGN hRGN, BOOL fErase)
{
::InvalidateRgn(_hwnd, hRGN, fErase);
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::ScrollRect [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::AdjustRect [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::AdjustRect(LPRECT prc)
{
return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnDefWindowMessage [IOleInPlaceSiteWindowless]
//
HRESULT CControlHost::OnDefWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
{
*plResult = ::DefWindowProc(_hwnd, msg, wParam, lParam);
return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetBorder [IOleInPlaceUIWindow]
//
HRESULT CControlHost::GetBorder(LPRECT lprectBorder)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::RequestBorderSpace [IOleInPlaceUIWindow]
//
HRESULT CControlHost::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::SetBorderSpace [IOleInPlaceUIWindow]
//
HRESULT CControlHost::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
{
if(_punkOuter)
return ((CControlHost*)_punkOuter)->SetBorderSpace(lpborderwidths);

return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::SetActiveObject [IOleInPlaceUIWindow]
//
HRESULT CControlHost::SetActiveObject(IOleInPlaceActiveObject * pActiveObject, LPCOLESTR lpszObjName)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::InsertMenus [IOleInPlaceFrame]
//
HRESULT CControlHost::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::SetMenu [IOleInPlaceFrame]
//
HRESULT CControlHost::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::RemoveMenus [IOleInPlaceFrame]
//
HRESULT CControlHost::RemoveMenus(HMENU hmenuShared)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::SetStatusText [IOleInPlaceFrame]
//
HRESULT CControlHost::SetStatusText(LPCOLESTR pszStatusText)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::EnableModeless [IOleInPlaceFrame]
//
HRESULT CControlHost::EnableModeless(BOOL fEnable)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::TranslateAccelerator [IOleInPlaceFrame]
//
HRESULT CControlHost::TranslateAccelerator(LPMSG lpmsg, WORD wID)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnControlInfoChanged [IOleControlSite]
//
HRESULT CControlHost::OnControlInfoChanged()
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::LockInPlaceActive [IOleControlSite]
//
HRESULT CControlHost::LockInPlaceActive(BOOL fLock)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetExtendedControl [IOleControlSite]
//
HRESULT CControlHost::GetExtendedControl(IDispatch **ppDisp)
{
if (ppDisp == NULL)
return (E_INVALIDARG);

*ppDisp = (IDispatch *)this;
AddRef();

return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::TransformCoords [IOleControlSite]
//
HRESULT CControlHost::TransformCoords(POINTL *pptlHimetric, POINTF *pptfContainer, DWORD dwFlags)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::TranslateAccelerator [IOleControlSite]
//
HRESULT CControlHost::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
{
return (S_FALSE);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::OnFocus [IOleControlSite]
//
HRESULT CControlHost::OnFocus(BOOL fGotFocus)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::ShowPropertyFrame [IOleControlSite]
//
HRESULT CControlHost::ShowPropertyFrame(void)
{
return (E_NOTIMPL);
}


//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetIDsOfNames [IDispatch]
//
HRESULT CControlHost::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
{
HRESULT hr; // standard ole return code
LPOLESTR pName;
DISPID *pdispid;

hr = S_OK;
pName = *rgszNames;
pdispid = rgdispid;

for (UINT i=0; i<cNames; i++)
{
if (pName != NULL)
{
if (_wcsicmp(pName, L"basehref") == 0)
*pdispid = DISPID_BASEHREF;
else if (_wcsicmp(pName, L"align") == 0)
*pdispid = DISPID_ALIGN;
else
{
*pdispid = DISPID_UNKNOWN;
hr = DISP_E_UNKNOWNNAME;
}
}

pdispid++;
pName++;
}

return (hr);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetTypeInfo [IDispatch]
//
HRESULT CControlHost::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::GetTypeInfoCount [IDispatch]
//
HRESULT CControlHost::GetTypeInfoCount(unsigned int FAR * pctinfo)
{
return (E_NOTIMPL);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::Invoke [IDispatch]
//
HRESULT CControlHost::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
{
HRESULT hr = S_OK; // standard ole return code

// The following code are the DISPIDs for the ambient properties
// that we will support.
if ((pvarResult == NULL) && (wFlags == DISPATCH_PROPERTYGET))
return (E_INVALIDARG);

switch (dispid)
{
case DISPID_NAVIGATECOMPLETE:
hr = S_OK;

case DISPID_AMBIENT_DISPLAYNAME:
if (!pvarResult->bstrVal)
pvarResult->bstrVal = ::SysAllocString(L"");

hr = S_OK;

// If we STILL don't have a bstrVal. Clean up and return an empty variant.
if (!pvarResult->bstrVal)
{
VariantInit(pvarResult);
hr = E_FAIL;
}

break;

case DISPID_AMBIENT_USERMODE:
case DISPID_AMBIENT_MESSAGEREFLECT:
pvarResult->vt = VT_BOOL;
pvarResult->boolVal = TRUE;
hr = S_OK;
break;

case DISPID_AMBIENT_SHOWHATCHING:
case DISPID_AMBIENT_SHOWGRABHANDLES:
case DISPID_AMBIENT_SUPPORTSMNEMONICS:
pvarResult->vt = VT_BOOL;
pvarResult->boolVal = FALSE;
hr = S_OK;
break;

// Not yet implemented!
case DISPID_AMBIENT_BACKCOLOR:
case DISPID_AMBIENT_FORECOLOR:
case DISPID_AMBIENT_UIDEAD:
case DISPID_AMBIENT_AUTOCLIP:
hr = S_OK;
break;

// Extender Properties
case DISPID_BASEHREF:
case DISPID_ALIGN:
hr = DISP_E_MEMBERNOTFOUND;
break;

default:
hr = DISP_E_MEMBERNOTFOUND;
}

return (hr);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::CreateControl [HELPER]
//
HRESULT CControlHost::CreateControl()
{
HRESULT hr; // standard ole return code
IOleObject *pIOleObject; // IOleObject interface pointer
IPersistStreamInit *pps; // IPersistStreamInit interface pointer

// Create a DAViewerControl.
_pvc = new CDAViewerCtl();

// Check if the creation succeeded.
if (!_pvc)
return E_OUTOFMEMORY;

hr = _pvc->GetIUnknown(&_punk);
if (FAILED(hr)) {
return (hr);
}

AddRef(); // addref the container

hr = _punk->QueryInterface(IID_IOleObject, (LPVOID *)&pIOleObject);

if (SUCCEEDED(hr))
{
pIOleObject->SetClientSite(this);

// Controls like to know they have been initialized by getting
// called on their InitNew method.
hr = _punk->QueryInterface(IID_IPersistStreamInit, (LPVOID *)&pps);
if (SUCCEEDED(hr))
{
pps->InitNew();
pps->Release();
}

// The control creation succeeded, lets create the model.
_pvc->CreateModel();

// Tell the control to activate and show itself.
pIOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, _hwnd, &_rcPos);
pIOleObject->DoVerb(OLEIVERB_SHOW, NULL, this, 0, _hwnd, &_rcPos);
pIOleObject->Release();

// cache some frequently needed interface pointers
// cache the control's window handle
_hwndControl = NULL;
IOleInPlaceActiveObject *pipao = NULL;
hr = _punk->QueryInterface(IID_IOleInPlaceActiveObject, (void**) &pipao);
if (SUCCEEDED(hr))
{
pipao->GetWindow(&_hwndControl);
pipao->Release();
}
}
return (hr);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::DeleteControl [HELPER]
//
HRESULT CControlHost::DeleteControl()
{
HRESULT hr; // standard ole return code
IOleObject *pIOleObject; // IOleObject interface pointer

if (_pvc != NULL)
{
delete _pvc;
_pvc = NULL;
}

// Close the Control and release the cached pointers.
if (_punk != NULL)
{
hr = _punk->QueryInterface(IID_IOleObject, (LPVOID *)&pIOleObject);
if (SUCCEEDED(hr))
{
pIOleObject->DoVerb(OLEIVERB_HIDE, NULL, this, 0, _hwnd, NULL);
pIOleObject->Close(OLECLOSE_NOSAVE);
pIOleObject->SetClientSite(NULL);
pIOleObject->Release();

_punk->Release();
_punk = NULL;
}

Release(); // Release our hold on the container
}

return (S_OK);
}

//////////////////////////////////////////////////////////////////////////
//
// CControlHost::QueryObject [HELPER]
//
HRESULT CControlHost::QueryObject(REFIID riid, void **ppvObject)
{
HRESULT hr = E_POINTER;
if (ppvObject)
{
if (_punk)
{
hr = _punk->QueryInterface(riid, ppvObject);
}
else
{
*ppvObject = NULL;
hr = OLE_E_NOCONNECTION;
}
}
return hr;
}