Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

715 lines
16 KiB

//////////////////////////////////////////////////////////////////////////
//
// container.cpp
//
// This file contains the complete implementation of an ActiveX
// control container. This purpose of this container is to test
// a single control being hosted.
//
// (C) Copyright 1997 by Microsoft Corporation. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include <shlguid.h>
#include "contain.h"
/**
* This method is the constructor for the CContainer object.
*/
CContainer::CContainer()
{
m_cRefs = 1;
m_hwnd = NULL;
m_punk = NULL;
memset(&m_rect, 0, sizeof(m_rect));
}
/**
* This method is the destructor for the CContainer object.
*/
CContainer::~CContainer()
{
if (m_punk)
{
m_punk->Release();
m_punk=NULL;
}
}
/**
* This method is called when the caller wants an interface pointer.
*
* @param riid The interface being requested.
* @param ppvObject The resultant object pointer.
*
* @return HRESULT S_OK, E_POINTER, E_NOINTERFACE
*/
STDMETHODIMP CContainer::QueryInterface(REFIID riid, PVOID *ppvObject)
{
if (!ppvObject)
return E_POINTER;
//~ if (IsEqualIID(riid, IID_IOleClientSite))
//~ *ppvObject = (IOleClientSite *)this;
//~ else if (IsEqualIID(riid, IID_IOleInPlaceSite))
if (IsEqualIID(riid, IID_IOleInPlaceSite))
*ppvObject = (IOleInPlaceSite *)this;
//~ else if (IsEqualIID(riid, IID_IOleInPlaceFrame))
//~ *ppvObject = (IOleInPlaceFrame *)this;
//~ else if (IsEqualIID(riid, IID_IOleInPlaceUIWindow))
//~ *ppvObject = (IOleInPlaceUIWindow *)this;
//~ else if (IsEqualIID(riid, IID_IOleControlSite))
//~ *ppvObject = (IOleControlSite *)this;
else if (IsEqualIID(riid, IID_IOleWindow))
*ppvObject = (IOleWindow *)(IOleInPlaceFrame *)this;
//~ else if (IsEqualIID(riid, IID_IDispatch))
//~ *ppvObject = (IDispatch *)this;
else if (IsEqualIID(riid, IID_IUnknown))
*ppvObject = this;
//~ else if (IsEqualIID(riid, IID_IOleCommandTarget))
//~ *ppvObject = (IOleCommandTarget *)this;
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
/**
* This method increments the current object count.
*
* @return ULONG The new reference count.
*/
ULONG CContainer::AddRef(void)
{
return ++m_cRefs;
}
/**
* This method decrements the object count and deletes if necessary.
*
* @return ULONG Remaining ref count.
*/
ULONG CContainer::Release(void)
{
if (--m_cRefs)
return m_cRefs;
delete this;
return 0;
}
// ***********************************************************************
// IOleClientSite
// ***********************************************************************
HRESULT CContainer::SaveObject()
{
return E_NOTIMPL;
}
HRESULT CContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER * ppMk)
{
return E_NOTIMPL;
}
HRESULT CContainer::GetContainer(LPOLECONTAINER * ppContainer)
{
return E_NOINTERFACE;
}
HRESULT CContainer::ShowObject()
{
return S_OK;
}
HRESULT CContainer::OnShowWindow(BOOL fShow)
{
return S_OK;
}
HRESULT CContainer::RequestNewObjectLayout()
{
return E_NOTIMPL;
}
// ***********************************************************************
// IOleWindow
// ***********************************************************************
HRESULT CContainer::GetWindow(HWND * lphwnd)
{
if (!IsWindow(m_hwnd))
return S_FALSE;
*lphwnd = m_hwnd;
return S_OK;
}
HRESULT CContainer::ContextSensitiveHelp(BOOL fEnterMode)
{
return E_NOTIMPL;
}
// ***********************************************************************
// IOleInPlaceSite
// ***********************************************************************
HRESULT CContainer::CanInPlaceActivate(void)
{
return S_OK;
}
HRESULT CContainer::OnInPlaceActivate(void)
{
return S_OK;
}
HRESULT CContainer::OnUIActivate(void)
{
return S_OK;
}
HRESULT CContainer::GetWindowContext (IOleInPlaceFrame ** ppFrame, IOleInPlaceUIWindow ** ppIIPUIWin,
LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
{
//~ *ppFrame = (IOleInPlaceFrame *)this;
*ppFrame = NULL;
*ppIIPUIWin = NULL;
RECT rect;
GetClientRect(m_hwnd, &rect);
lprcPosRect->left = 0;
lprcPosRect->top = 0;
lprcPosRect->right = rect.right;
lprcPosRect->bottom = rect.bottom;
CopyRect(lprcClipRect, lprcPosRect);
lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
lpFrameInfo->fMDIApp = FALSE;
lpFrameInfo->hwndFrame = m_hwnd;
lpFrameInfo->haccel = 0;
lpFrameInfo->cAccelEntries = 0;
//~ (*ppFrame)->AddRef();
return S_OK;
}
HRESULT CContainer::Scroll(SIZE scrollExtent)
{
return E_NOTIMPL;
}
HRESULT CContainer::OnUIDeactivate(BOOL fUndoable)
{
return E_NOTIMPL;
}
HRESULT CContainer::OnInPlaceDeactivate(void)
{
return S_OK;
}
HRESULT CContainer::DiscardUndoState(void)
{
return E_NOTIMPL;
}
HRESULT CContainer::DeactivateAndUndo(void)
{
return E_NOTIMPL;
}
HRESULT CContainer::OnPosRectChange(LPCRECT lprcPosRect)
{
return S_OK;
}
// ***********************************************************************
// IOleInPlaceUIWindow
// ***********************************************************************
HRESULT CContainer::GetBorder(LPRECT lprectBorder)
{
return E_NOTIMPL;
}
HRESULT CContainer::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
{
return E_NOTIMPL;
}
HRESULT CContainer::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
{
return E_NOTIMPL;
}
HRESULT CContainer::SetActiveObject(IOleInPlaceActiveObject * pActiveObject, LPCOLESTR lpszObjName)
{
return E_NOTIMPL;
}
// ***********************************************************************
// IOleInPlaceFrame
// ***********************************************************************
HRESULT CContainer::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
{
return E_NOTIMPL;
}
HRESULT CContainer::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
{
return E_NOTIMPL;
}
HRESULT CContainer::RemoveMenus(HMENU hmenuShared)
{
return E_NOTIMPL;
}
HRESULT CContainer::SetStatusText(LPCOLESTR pszStatusText)
{
char status[MAX_PATH]; // ansi version of status text
if (NULL == pszStatusText)
return E_POINTER;
WideCharToMultiByte(CP_ACP, 0, pszStatusText, -1, status, MAX_PATH, NULL, NULL);
if (IsWindow(m_hwndStatus))
SendMessage(m_hwndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)status);
return (S_OK);
}
HRESULT CContainer::EnableModeless(BOOL fEnable)
{
return E_NOTIMPL;
}
HRESULT CContainer::TranslateAccelerator(LPMSG lpmsg, WORD wID)
{
return S_FALSE;
}
// ***********************************************************************
// IOleControlSite
// ***********************************************************************
HRESULT CContainer::OnControlInfoChanged()
{
return E_NOTIMPL;
}
HRESULT CContainer::LockInPlaceActive(BOOL fLock)
{
return E_NOTIMPL;
}
HRESULT CContainer::GetExtendedControl(IDispatch **ppDisp)
{
if (ppDisp == NULL)
return E_INVALIDARG;
*ppDisp = (IDispatch *)this;
(*ppDisp)->AddRef();
return S_OK;
}
HRESULT CContainer::TransformCoords(POINTL *pptlHimetric, POINTF *pptfContainer, DWORD dwFlags)
{
return E_NOTIMPL;
}
HRESULT CContainer::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
{
return S_FALSE;
}
HRESULT CContainer::OnFocus(BOOL fGotFocus)
{
return E_NOTIMPL;
}
HRESULT CContainer::ShowPropertyFrame(void)
{
return E_NOTIMPL;
}
// ***********************************************************************
// IDispatch
// ***********************************************************************
HRESULT CContainer::GetIDsOfNames(REFIID riid, OLECHAR FAR* FAR* rgszNames, unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
{
*rgdispid = DISPID_UNKNOWN;
return DISP_E_UNKNOWNNAME;
}
HRESULT CContainer::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
{
return E_NOTIMPL;
}
HRESULT CContainer::GetTypeInfoCount(unsigned int FAR * pctinfo)
{
return E_NOTIMPL;
}
HRESULT CContainer::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS FAR *pdispparams, VARIANT FAR *pvarResult, EXCEPINFO FAR * pexecinfo, unsigned int FAR *puArgErr)
{
return DISP_E_MEMBERNOTFOUND;
}
// ***********************************************************************
// IOleCommandTarget
// ***********************************************************************
HRESULT CContainer::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[ ], OLECMDTEXT *pCmdText)
{
HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
const int SBCMDID_ADDTOFAVORITES = 8;
#if 0
if (pguidCmdGroup && IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
{
for (ULONG i=0 ; i < cCmds ; i++)
{
switch (rgCmds[i].cmdID)
{
case SBCMDID_ADDTOFAVORITES:
rgCmds[i].cmdf = OLECMDF_ENABLED | OLECMDF_SUPPORTED;
break;
default:
rgCmds[i].cmdf = 0;
break;
}
}
hres = S_OK;
}
#endif
return hres;
}
HRESULT CContainer::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
HRESULT hres = OLECMDERR_E_UNKNOWNGROUP;
const int SBCMDID_ADDTOFAVORITES = 8;
#if 0
if (pguidCmdGroup && IsEqualGUID(CGID_Explorer, *pguidCmdGroup))
{
switch(nCmdID)
{
case SBCMDID_ADDTOFAVORITES:
TCHAR szURL[2048];
TCHAR szTitle[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, pvaIn->bstrVal, -1, szURL, sizeof(szURL), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, pvaOut->bstrVal, -1, szTitle, sizeof(szTitle), NULL, NULL);
MessageBox(m_hwnd,
szURL,
szTitle,
MB_OK);
hres = S_OK;
break;
}
}
#endif
return hres;
}
// ***********************************************************************
// Public (non-interface) Methods
// ***********************************************************************
/**
* This method will add an ActiveX control to the container. Note, for
* now, this CContainer can only have one control.
*
* @param bstrClsid The CLSID or PROGID of the control.
*
* @return HRESULT S_OK, E_POINTER, E_NOINTERFACE
*/
HRESULT CContainer::add(BSTR bstrClsid)
{
CLSID clsid; // CLSID of the control object
HRESULT hr; // return code
hr = CLSIDFromString(bstrClsid, &clsid);
if (FAILED(hr))
return hr;
hr = CoCreateInstance(clsid,
NULL,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IID_IUnknown,
(PVOID *)&m_punk);
if (FAILED(hr))
return hr;
ASSERT(NULL != m_punk);
IOleObject *pioo;
hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
if (FAILED(hr))
return hr;
pioo->SetClientSite(this);
pioo->Release();
IPersistStreamInit *ppsi;
hr = m_punk->QueryInterface(IID_IPersistStreamInit, (PVOID *)&ppsi);
if (SUCCEEDED(hr))
{
ppsi->InitNew();
ppsi->Release();
}
return hr;
}
/**
* This method will remove the control from the container.
*
* @return No return value.
*/
void CContainer::remove()
{
if (!m_punk)
return;
HRESULT hr;
IOleObject *pioo;
IOleInPlaceObject *pipo;
hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
if (SUCCEEDED(hr))
{
pioo->Close(OLECLOSE_NOSAVE);
pioo->SetClientSite(NULL);
pioo->Release();
}
hr = m_punk->QueryInterface(IID_IOleInPlaceObject, (PVOID *)&pipo);
if (SUCCEEDED(hr))
{
pipo->UIDeactivate();
pipo->InPlaceDeactivate();
pipo->Release();
}
m_punk->Release();
m_punk = NULL;
}
/**
* This method sets the parent window. This is used by the container
* so the control can parent itself.
*
* @param hwndParent The parent window handle.
*
* @return No return value.
*/
void CContainer::setParent(HWND hwndParent)
{
m_hwnd = hwndParent;
}
/**
* This method will set the location of the control.
*
* @param x The top left.
* @param y The top right.
* @param width The width of the control.
* @param height The height of the control.
*/
void CContainer::setLocation(int x, int y, int width, int height)
{
m_rect.left = x;
m_rect.top = y;
m_rect.right = x + width;
m_rect.bottom = y + height;
if (!m_punk)
return;
HRESULT hr;
IOleInPlaceObject *pipo;
hr = m_punk->QueryInterface(IID_IOleInPlaceObject, (PVOID *)&pipo);
if (FAILED(hr))
return;
pipo->SetObjectRects(&m_rect, &m_rect);
pipo->Release();
}
HRESULT CContainer::InPlaceActivate( void )
{
HRESULT hr = E_FAIL;
if( m_punk )
{
CComQIPtr< IOleObject, &IID_IOleObject > spioo( m_punk );
if( spioo != NULL )
{
spioo->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, m_hwnd, &m_rect);
spioo->DoVerb(OLEIVERB_HIDE, NULL, this, 0, m_hwnd, &m_rect);
}
}
return hr;
}
/**
* Sets the visible state of the control.
*
* @param fVisible TRUE=visible, FALSE=hidden
* @return No return value.
*/
void CContainer::setVisible(BOOL fVisible)
{
if (!m_punk)
return;
HRESULT hr;
IOleObject *pioo;
hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
if (FAILED(hr))
return;
if (fVisible)
{
pioo->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, m_hwnd, &m_rect);
pioo->DoVerb(OLEIVERB_SHOW, NULL, this, 0, m_hwnd, &m_rect);
IOleInPlaceObject *pipo;
HRESULT hr = m_punk->QueryInterface(IID_IOleInPlaceObject, (PVOID *)&pipo);
if (SUCCEEDED(hr))
{
pipo->SetObjectRects(&m_rect, &m_rect);
pipo->Release();
}
}
else
pioo->DoVerb(OLEIVERB_HIDE, NULL, this, 0, m_hwnd, NULL);
pioo->Release();
}
/**
* This sets the focus to the control (a.k.a. UIActivate)
*
* @param fFocus TRUE=set, FALSE=remove
*
* @return No return value.
*/
void CContainer::setFocus(BOOL fFocus)
{
if (!m_punk)
return;
HRESULT hr;
IOleObject *pioo;
if (fFocus)
{
hr = m_punk->QueryInterface(IID_IOleObject, (PVOID *)&pioo);
if (FAILED(hr))
return;
pioo->DoVerb(OLEIVERB_UIACTIVATE, NULL, this, 0, m_hwnd, &m_rect);
pioo->Release();
}
}
/**
* If the container has an HWND for the status window (must be
* common control), then this method is used to tell the container.
*
* @param hwndStatus Window handle of the status bar.
*
* @return No return value.
*/
void CContainer::setStatusWindow(HWND hwndStatus)
{
m_hwndStatus = hwndStatus;
}
/**
* This method gives the control the opportunity to translate and use
* key strokes.
*
* @param msg Key message.
*
* @return No return value.
*/
HRESULT CContainer::translateKey(MSG *pmsg)
{
if (!m_punk)
return E_FAIL;
HRESULT hr;
IOleInPlaceActiveObject *pao;
hr = m_punk->QueryInterface(IID_IOleInPlaceActiveObject, (PVOID *)&pao);
if (FAILED(hr))
return hr;
hr = pao->TranslateAccelerator(pmsg);
pao->Release();
return hr;
}
/**
* Returns the IDispatch pointer of the contained control. Note, the
* caller is responsible for calling IDispatch::Release().
*
* @return Controls dispatch interface.
*/
IDispatch * CContainer::getDispatch()
{
if (!m_punk)
return NULL;
HRESULT hr;
IDispatch *pdisp;
hr = m_punk->QueryInterface(IID_IDispatch, (PVOID *)&pdisp);
return pdisp;
}
/**
* Returns the IUnknown interface pointer for the containd control. Note,
* the caller is responsible for calling IUnknown::Release().
*
* @return Controls unknown interface.
*/
IUnknown * CContainer::getUnknown()
{
if (!m_punk)
return NULL;
m_punk->AddRef();
return m_punk;
}