Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3010 lines
80 KiB

#include "precomp.h"
#define __MARS_INLINE_FAST_IS_EQUAL_GUID
#define LIGHTWEIGHT_AUTOPERSIST
#define BLOCK_PANEL_RENAVIGATES
#include "mcinc.h"
#include <evilguid.h>
#include "marswin.h"
#include "pandef.h"
#include "panel.h"
#include "place.h"
#include "htiface.h"
#include "mimeinfo.h"
#include <exdispid.h>
#include "dllload.h"
#include <perhist.h>
#include <mshtmcid.h>
#include <strsafe.h>
#include <msiehost.h>
// We include this cpp file because the stuff
// in pandef needs to be included in another project
// namely, parser\comptree
#include "pandef.cpp"
// CLSID strings passed to ATL to create control
static WCHAR wszCLSID_HTMLDocument[] = L"{25336920-03F9-11CF-8FD0-00AA00686F13}";
static WCHAR wszCLSID_WebBrowser[] = L"{8856F961-340A-11D0-A96B-00C04FD705A2}";
static WCHAR wszCLSID_HTADocument[] = L"{3050f5c8-98b5-11cf-bb82-00aa00bdce0b}";
const GUID CLSID_HTADoc = { 0x3050f5c8, 0x98b5, 0x11cf, { 0xbb, 0x82, 0x00, 0xaa, 0x00, 0xbd, 0xce, 0x0b } };
// CLASS_CMarsPanel = {EE0462C2-5CD3-11d3-97FA-00C04F45D0B3}
const GUID CLASS_CMarsPanel = { 0xee0462c2, 0x5cd3, 0x11d3, { 0x97, 0xfa, 0x0, 0xc0, 0x4f, 0x45, 0xd0, 0xb3 } };
CMarsPanel::CMarsPanel(CPanelCollection *pParent, CMarsWindow *pMarsWindow) :
m_MarsExternal(this, pMarsWindow),
m_BrowserEvents(this)
{
m_spPanelCollection = pParent;
m_spMarsDocument = m_spPanelCollection->Document();
m_lReadyState = READYSTATE_COMPLETE;
}
CMarsPanel::~CMarsPanel()
{
}
HRESULT CMarsPanel::Passivate()
{
return CMarsComObject::Passivate();
}
HRESULT CMarsPanel::DoPassivate()
{
m_spMarsDocument->MarsWindow()->NotifyHost(MARSHOST_ON_PANEL_PASSIVATE, SAFECAST(this, IMarsPanel *), 0);
m_spPanelCollection->SetActivePanel(this, FALSE);
// First we unload the document so that script can do work in its "onunload"
// handler, before we become passive
if(IsWebBrowser())
{
CComPtr<IUnknown> spUnk;
if (SUCCEEDED(m_Content.QueryControl(IID_IUnknown, (void **)&spUnk)))
{
m_BrowserEvents.Connect(spUnk, FALSE);
}
}
else if(IsCustomControl())
{
}
else
{
DisconnectCompletionAdviser();
}
m_Content.DestroyWindow();
////////////////////////////////////////
m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects(SAFECAST(this, IDispatch *));
m_BrowserEvents.Passivate();
m_MarsExternal.Passivate();
m_spBrowserService.Release();
m_spPanelCollection.Release();
m_spMarsDocument.Release();
return S_OK;
}
// IUnknown
IMPLEMENT_ADDREF_RELEASE(CMarsPanel);
STDMETHODIMP CMarsPanel::QueryInterface(REFIID iid, void ** ppvObject)
{
ATLASSERT(ppvObject);
if ((iid == IID_IUnknown) ||
(iid == IID_IDispatch) ||
(iid == IID_IMarsPanel))
{
*ppvObject = SAFECAST(this, IMarsPanel *);
}
else if (iid == IID_IHlinkFrame)
{
*ppvObject = SAFECAST(this, IHlinkFrame *);
}
else if (iid == IID_IServiceProvider)
{
*ppvObject = SAFECAST(this, IServiceProvider *);
}
else if (iid == IID_IInternetSecurityManager)
{
*ppvObject = SAFECAST(this, IInternetSecurityManager *);
}
else if ((iid == IID_IOleInPlaceSite) || (iid == IID_IOleWindow))
{
*ppvObject = SAFECAST(this, IOleInPlaceSite *);
}
else if (iid == IID_IOleControlSite)
{
*ppvObject = SAFECAST(this, IOleControlSite *);
}
else if (iid == IID_IPropertyNotifySink)
{
*ppvObject = SAFECAST(this, IPropertyNotifySink *);
}
else if (iid == IID_IProfferService)
{
*ppvObject = SAFECAST(this, IProfferService *);
}
else if (iid == IID_IOleInPlaceUIWindow)
{
*ppvObject = SAFECAST(this, IOleInPlaceUIWindow *);
}
else if (iid == CLASS_CMarsPanel)
{
*ppvObject = SAFECAST(this, CMarsPanel *);
}
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
HRESULT CMarsPanel::DoEnableModeless(BOOL fEnable)
{
CComPtr<IOleInPlaceActiveObject> spOleInPlaceActiveObject;
HRESULT hr = m_Content.QueryControl(&spOleInPlaceActiveObject);
if (SUCCEEDED(hr))
{
spOleInPlaceActiveObject->EnableModeless(fEnable);
}
return hr;
}
//==================================================================
// Automation Object Model
//==================================================================
//------------------------------------------------------------------------------
// IMarsPanel::get_name
//
HRESULT CMarsPanel::get_name( BSTR *pbstrName )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( pbstrName ))
{
*pbstrName = SysAllocString( GetName() );
hr = (NULL != *pbstrName) ? S_OK : E_OUTOFMEMORY;
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_content
//
HRESULT CMarsPanel::get_content( IDispatch* *ppVal )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( ppVal ))
{
*ppVal = NULL;
if(VerifyNotPassive( &hr ))
{
CreateControl();
hr = m_Content.QueryControl( ppVal );
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_visible
//
HRESULT CMarsPanel::get_visible( VARIANT_BOOL *pbVisible )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( pbVisible ))
{
if(VerifyNotPassive( &hr ))
{
*pbVisible = VARIANT_BOOLIFY( m_fVisible );
hr = S_OK;
}
else
{
*pbVisible = VARIANT_FALSE;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_visible
//
HRESULT CMarsPanel::put_visible( VARIANT_BOOL bVisible )
{
ATLASSERT(IsValidVariantBoolVal( bVisible ));
HRESULT hr = S_OK;
if(VerifyNotPassive( &hr ))
{
if(!!m_fVisible != !!bVisible)
{
m_fVisible = (bVisible != VARIANT_FALSE);
if(!m_fVisible)
{
m_spPanelCollection->SetActivePanel( this, FALSE );
}
// If the theme has changed while the panel was invisible,
// now is a good time to automatically update it
if(m_fVisible && IsContentInvalid())
{
refresh();
}
OnLayoutChange();
}
else
{
hr = S_FALSE;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_startUrl
//
HRESULT CMarsPanel::get_startUrl( BSTR *pVal )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( pVal ))
{
*pVal = m_bstrStartUrl.Copy();
hr = S_OK;
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_startUrl
//
HRESULT CMarsPanel::put_startUrl( BSTR newVal )
{
HRESULT hr = S_OK;
m_bstrStartUrl = newVal;
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_height
//
HRESULT CMarsPanel::get_height( long *plHeight )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( plHeight ))
{
if(VerifyNotPassive( &hr ))
{
hr = S_OK;
if(m_Content.IsWindowVisible())
{
// Use actual position
RECT rc;
m_Content.GetWindowRect( &rc );
*plHeight = rc.bottom - rc.top;
}
else
{
// Panel's hidden. Return requested position.
*plHeight = m_lHeight;
}
}
else
{
*plHeight = 0;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_height
//
HRESULT CMarsPanel::put_height( long lHeight )
{
ATLASSERT(lHeight >= 0);
HRESULT hr = S_OK;
if(VerifyNotPassive( &hr ))
{
if(lHeight >= 0)
{
if(m_lMinHeight >= 0 && lHeight < m_lMinHeight) lHeight = m_lMinHeight;
if(m_lMaxHeight >= 0 && lHeight > m_lMaxHeight) lHeight = m_lMaxHeight;
if(m_lHeight != lHeight)
{
m_lHeight = lHeight;
OnLayoutChange();
}
}
else
{
hr = S_FALSE;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_width
//
HRESULT CMarsPanel::get_width( long *plWidth )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( plWidth ))
{
if(VerifyNotPassive( &hr ))
{
if(m_Content.IsWindowVisible())
{
// Use actual position
RECT rc;
m_Content.GetWindowRect( &rc );
*plWidth = rc.right - rc.left;
}
else
{
// Panel's hidden. Return requested position.
*plWidth = m_lWidth;
}
hr = S_OK;
}
else
{
*plWidth = 0;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_width
//
HRESULT CMarsPanel::put_width( long lWidth )
{
ATLASSERT(lWidth >= 0);
HRESULT hr = S_OK;
if(VerifyNotPassive( &hr ))
{
if(lWidth >= 0)
{
if(m_lMinWidth >= 0 && lWidth < m_lMinWidth) lWidth = m_lMinWidth;
if(m_lMaxWidth >= 0 && lWidth > m_lMaxWidth) lWidth = m_lMaxWidth;
if(m_lWidth != lWidth)
{
m_lWidth = lWidth;
OnLayoutChange();
}
}
else
{
hr = S_FALSE;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_x
//
HRESULT CMarsPanel::get_x( long *plX )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( plX ))
{
if(VerifyNotPassive( &hr ))
{
hr = S_OK;
if(m_Content.IsWindowVisible())
{
// Use actual position
RECT rc;
GetMyClientRectInParentCoords( &rc );
*plX = rc.left;
}
else
{
// Panel's hidden. Return requested position.
*plX = m_lX;
}
}
else
{
*plX = 0;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_x
//
HRESULT CMarsPanel::put_x( long lX )
{
HRESULT hr = S_OK;
if(VerifyNotPassive( &hr ))
{
if(m_lX != lX)
{
m_lX = lX;
if(IsPopup())
{
OnLayoutChange();
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_y
//
HRESULT CMarsPanel::get_y( long *plY )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( plY ))
{
if(VerifyNotPassive( &hr ))
{
hr = S_OK;
if(m_Content.IsWindowVisible())
{
// Use actual position
RECT rc;
GetMyClientRectInParentCoords( &rc );
*plY = rc.top;
}
else
{
*plY = m_lY;
}
}
else
{
*plY = 0;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_y
//
HRESULT CMarsPanel::put_y( long lY )
{
HRESULT hr = S_OK;
if(VerifyNotPassive( &hr ))
{
if(m_lY != lY)
{
m_lY = lY;
if(IsPopup())
{
OnLayoutChange();
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_position
//
HRESULT CMarsPanel::get_position( VARIANT *pvarPosition )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( pvarPosition ))
{
if(VerifyNotPassive( &hr ))
{
VariantClear( pvarPosition );
hr = S_FALSE;
if(m_Position <= c_iPositionMapSize)
{
pvarPosition->bstrVal = SysAllocString( s_PositionMap[m_Position].pwszName );
if(pvarPosition->bstrVal)
{
pvarPosition->vt = VT_BSTR;
hr = S_OK;
}
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_position
//
HRESULT CMarsPanel::put_position( VARIANT varPosition )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidVariantBstr( varPosition ))
{
if(VerifyNotPassive( &hr ))
{
hr = SCRIPT_ERROR;
PANEL_POSITION position;
if(SUCCEEDED(StringToPanelPosition( varPosition.bstrVal, &position )))
{
hr = S_OK;
if(m_Position != position)
{
m_Position = s_PositionMap[position].Position;
if(m_Position == PANEL_POPUP)
{
m_Content.SetWindowPos( HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE );
}
OnLayoutChange();
}
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_autoSize
//
HRESULT CMarsPanel::get_autoSize( VARIANT_BOOL *pbAutoSize )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( pbAutoSize ))
{
*pbAutoSize = VARIANT_BOOLIFY(IsAutoSizing());
if(VerifyNotPassive( &hr ))
{
hr = S_OK;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_autoSize
//
HRESULT CMarsPanel::put_autoSize( VARIANT_BOOL bAutoSize )
{
HRESULT hr = S_OK;
ATLASSERT(IsValidVariantBoolVal( bAutoSize ));
if(VerifyNotPassive( &hr ))
{
if(bAutoSize)
{
if(!IsAutoSizing())
{
m_dwFlags |= PANEL_FLAG_AUTOSIZE;
OnLayoutChange();
}
}
else
{
if(IsAutoSizing())
{
m_dwFlags &= ~PANEL_FLAG_AUTOSIZE;
OnLayoutChange();
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_contentInvalid
//
HRESULT CMarsPanel::get_contentInvalid( VARIANT_BOOL *pbInvalid )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( pbInvalid ))
{
*pbInvalid = VARIANT_BOOLIFY(m_fContentInvalid);
hr = S_OK;
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::put_contentInvalid
//
HRESULT CMarsPanel::put_contentInvalid( VARIANT_BOOL bInvalid )
{
ATLASSERT(IsValidVariantBoolVal( bInvalid ));
ATLASSERT(!IsPassive());
m_fContentInvalid = BOOLIFY( bInvalid );
return S_OK;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_layoutIndex
//
HRESULT CMarsPanel::get_layoutIndex( long *plIndex )
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidWritePtr( plIndex ))
{
if(VerifyNotPassive( &hr ))
{
hr = m_spPanelCollection->FindPanelIndex( this, plIndex );
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::moveto
//
HRESULT CMarsPanel::moveto( VARIANT vlX, VARIANT vlY, VARIANT vlWidth, VARIANT vlHeight )
{
HRESULT hr = S_OK;
ATLASSERT(vlX.vt == VT_NULL || vlX.vt == VT_I4);
ATLASSERT(vlY.vt == VT_NULL || vlY.vt == VT_I4);
ATLASSERT(vlWidth.vt == VT_NULL || vlWidth.vt == VT_I4);
ATLASSERT(vlHeight.vt == VT_NULL || vlHeight.vt == VT_I4);
if(VerifyNotPassive( &hr ))
{
long lX = VariantToI4( vlX );
long lY = VariantToI4( vlY );
long lWidth = VariantToI4( vlWidth );
long lHeight = VariantToI4( vlHeight );
if(( lX != m_lX ) ||
( lY != m_lY ) ||
(lWidth >= 0 && lWidth != m_lWidth ) ||
(lHeight >= 0 && lHeight != m_lHeight) )
{
m_lX = lX;
m_lY = lY;
if(lWidth >= 0) m_lWidth = lWidth;
if(lHeight >= 0) m_lHeight = lHeight;
OnLayoutChange();
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::restrictWidth
//
HRESULT CMarsPanel::restrictWidth( VARIANT vlMin, VARIANT vlMax, VARIANT vbstrMarker )
{
HRESULT hr = S_OK;
ATLASSERT(vlMin.vt == VT_EMPTY || vlMin.vt == VT_NULL || vlMin.vt == VT_BSTR || vlMin.vt == VT_I4);
ATLASSERT(vlMax.vt == VT_EMPTY || vlMax.vt == VT_NULL || vlMax.vt == VT_BSTR || vlMin.vt == VT_I4);
ATLASSERT((vbstrMarker.vt==VT_NULL) || (vbstrMarker.vt == VT_EMPTY));
if(VerifyNotPassive( &hr ))
{
m_lMaxWidth = m_lMinWidth = -1;
if(vlMin.vt != VT_NULL &&
vlMin.vt != VT_EMPTY )
{
CComVariant vlMin2; vlMin2.ChangeType( VT_I4, &vlMin );
m_lMinWidth = VariantToI4( vlMin2 );
}
if(vlMax.vt != VT_NULL &&
vlMax.vt != VT_EMPTY )
{
CComVariant vlMax2; vlMax2.ChangeType( VT_I4, &vlMax );
m_lMaxWidth = VariantToI4( vlMax2 );
}
if(m_lMaxWidth >= 0 && m_lMaxWidth < m_lMinWidth)
{
m_lMaxWidth = m_lMinWidth;
}
OnLayoutChange();
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::restrictHeight
//
HRESULT CMarsPanel::restrictHeight( VARIANT vlMin, VARIANT vlMax, VARIANT vbstrMarker )
{
HRESULT hr = S_OK;
ATLASSERT(vlMin.vt == VT_EMPTY || vlMin.vt == VT_NULL || vlMin.vt == VT_BSTR || vlMin.vt == VT_I4);
ATLASSERT(vlMax.vt == VT_EMPTY || vlMax.vt == VT_NULL || vlMax.vt == VT_BSTR || vlMin.vt == VT_I4);
ATLASSERT((vbstrMarker.vt==VT_NULL) || (vbstrMarker.vt == VT_EMPTY));
if(VerifyNotPassive( &hr ))
{
m_lMaxHeight = m_lMinHeight = -1;
if(vlMin.vt != VT_NULL &&
vlMin.vt != VT_EMPTY )
{
CComVariant vlMin2; vlMin2.ChangeType( VT_I4, &vlMin );
m_lMinHeight = VariantToI4( vlMin2 );
}
if(vlMax.vt != VT_NULL &&
vlMax.vt != VT_EMPTY )
{
CComVariant vlMax2; vlMax2.ChangeType( VT_I4, &vlMax );
m_lMaxHeight = VariantToI4( vlMax2 );
}
if(m_lMaxHeight >= 0 && m_lMaxHeight < m_lMinHeight) m_lMaxHeight = m_lMinHeight;
OnLayoutChange();
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::canResize
//
HRESULT CMarsPanel::canResize( long lDX, long lDY, VARIANT_BOOL *pVal )
{
long lWidthOld = m_lWidth;
long lHeightOld = m_lHeight;
RECT rcClient;
m_lWidth += lDX;
m_lHeight += lDY;
(void)m_spMarsDocument->Window()->GetClientRect( &rcClient );
if(m_spMarsDocument->MarsWindow()->CanLayout( rcClient ))
{
if(pVal) *pVal = VARIANT_TRUE;
}
else
{
if(pVal) *pVal = VARIANT_FALSE;
}
m_lWidth = lWidthOld;
m_lHeight = lHeightOld;
return S_OK;
}
//------------------------------------------------------------------------------
// IMarsPanel::activate
//
HRESULT CMarsPanel::activate()
{
m_Content.SendMessage(WM_SETFOCUS, 0, 0);
return S_OK;
}
//------------------------------------------------------------------------------
// IMarsPanel::insertBefore
//
HRESULT CMarsPanel::insertBefore(VARIANT varInsertBefore)
{
ATLASSERT(varInsertBefore.vt == VT_I4 || // index to insert before
varInsertBefore.vt == VT_BSTR || // panel name to insert before
varInsertBefore.vt == VT_DISPATCH); // panel object to insert before
HRESULT hr = E_INVALIDARG;
if (API_IsValidVariant(varInsertBefore))
{
if (VerifyNotPassive(&hr))
{
hr = E_FAIL;
long lIndex = -668;
switch(varInsertBefore.vt)
{
case VT_I4:
lIndex = varInsertBefore.lVal;
hr = S_OK;
break;
case VT_DISPATCH:
{
CComClassPtr<CMarsPanel> spPanel;
varInsertBefore.pdispVal->QueryInterface(CLASS_CMarsPanel, (void **)&spPanel);
if (spPanel)
{
hr = m_spPanelCollection->FindPanelIndex(spPanel, &lIndex);
}
break;
}
case VT_BSTR:
hr = m_spPanelCollection->FindPanelIndex(
m_spPanelCollection->FindPanel(varInsertBefore.bstrVal),
&lIndex);
break;
default:
ATLASSERT(0);
}
if (SUCCEEDED(hr))
{
// Successfully got an index to insert before
ATLASSERT(lIndex != -668);
// Get our current index
long lCurrentIndex;
if (SUCCEEDED(m_spPanelCollection->FindPanelIndex(this, &lCurrentIndex)))
{
ATLASSERT(lCurrentIndex != -1);
if (lIndex != lCurrentIndex)
{
m_spPanelCollection->InsertPanelFromTo(lCurrentIndex, lIndex);
OnLayoutChange();
}
}
else
{
ATLASSERT(!"FindPanelIndex failed!");
}
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::execMshtml
//
// execMshtml allows script to send a command directly to Trident. This is different from
// IWebBrowser2::ExecWB because ExecWB passes a NULL command group, which prevents Trident
// from responding to commands like IDM_FIND. Usually, we could accomplish this by calling
// the OM method execCommand, but Trident doesn't respond to execCommand("Find")
//
HRESULT CMarsPanel::execMshtml(DWORD nCmdID, DWORD nCmdExecOpt,
VARIANTARG *pvaIn, VARIANTARG *pvaOut)
{
HRESULT hr = E_INVALIDARG;
if (VerifyNotPassive(&hr))
{
CComPtr<IOleCommandTarget> spCmdTarget;
hr = m_Content.QueryControl(IID_IOleCommandTarget, (void **) &spCmdTarget);
if (SUCCEEDED(hr))
{
hr = spCmdTarget->Exec(&CGID_MSHTML, nCmdID, nCmdExecOpt, pvaIn, pvaOut);
}
hr = S_OK;
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::get_isCurrentlyVisible
//
HRESULT CMarsPanel::get_isCurrentlyVisible(VARIANT_BOOL *pbIsVisible)
{
HRESULT hr = E_INVALIDARG;
if (API_IsValidWritePtr(pbIsVisible))
{
if (VerifyNotPassive(&hr))
{
*pbIsVisible = VARIANT_BOOLIFY(m_Content.IsWindowVisible());
hr = S_OK;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IServiceProvider::QueryService
//
// First, we try to handle guidService, then we go to IProfferServiceImpl,
// then we go to the parent window.
//
HRESULT CMarsPanel::QueryService(REFGUID guidService, REFIID riid, void **ppv)
{
HRESULT hr = E_FAIL;
*ppv = NULL;
if (!IsPassive())
{
if (guidService == IID_IInternetProtocol)
{
// Yeah, we don't support this service. Stop asking us for it!
}
else if ((guidService == SID_SHlinkFrame) ||
(guidService == SID_SProfferService) ||
(guidService == SID_SMarsPanel))
{
hr = QueryInterface(riid, ppv);
}
else if (guidService == SID_SInternetSecurityManager)
{
if (IsTrusted())
{
hr = QueryInterface(riid, ppv);
}
}
if (FAILED(hr))
{
hr = IProfferServiceImpl::QueryService(guidService, riid, ppv);
}
}
if (FAILED(hr))
{
hr = m_spMarsDocument->MarsWindow()->QueryService(guidService, riid, ppv);
}
return hr;
}
//------------------------------------------------------------------------------
// IHlinkFrame::Navigate
//
HRESULT CMarsPanel::Navigate(DWORD grfHLNF, LPBC pbc,
IBindStatusCallback *pibsc, IHlink *pihlNavigate)
{
// BUGBUG: Call ReleasedOwnedObjects for this panel
HRESULT hr = E_FAIL;
CComPtr<IMoniker> spMk;
if (VerifyNotPassive())
{
pihlNavigate->GetMonikerReference(grfHLNF, &spMk, NULL);
if (spMk)
{
hr = NavigateMk(spMk);
}
}
return hr;
}
//------------------------------------------------------------------------------
HRESULT CMarsPanel::Create( MarsAppDef_Panel* pLayout)
{
ATLASSERT(!IsPassive());
m_bstrName = pLayout->szName;
m_Position = pLayout->Position;
m_lWidth = pLayout->lWidth;
m_lHeight = pLayout->lHeight;
m_lX = pLayout->lX;
m_lY = pLayout->lY;
m_dwFlags = pLayout->dwFlags;
m_lMinWidth = pLayout->lWidthMin;
m_lMinHeight = pLayout->lHeightMin;
m_lMaxWidth = pLayout->lWidthMax;
m_lMaxHeight = pLayout->lHeightMax;
m_fVisible = BOOLIFY(m_dwFlags & PANEL_FLAG_VISIBLE);
m_dwCookie = 0;
if(!IsAutoSizing())
{
switch(m_Position)
{
case PANEL_BOTTOM:
case PANEL_TOP:
if(m_lMinHeight < 0 && m_lMaxHeight < 0)
{
m_lMinHeight = m_lHeight;
m_lMaxHeight = m_lHeight;
}
break;
case PANEL_LEFT:
case PANEL_RIGHT:
if(m_lMinWidth < 0 && m_lMaxWidth < 0)
{
m_lMinWidth = m_lWidth;
m_lMaxWidth = m_lWidth;
}
break;
}
}
{
DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
RECT rcCreate = { 0, 0, 0, 0 };
m_Content.Create( m_spMarsDocument->Window()->m_hWnd, &rcCreate, _T(""), dwStyle, 0 );
}
{
CComPtr<IObjectWithSite> spObj;
m_Content.QueryHost(IID_IObjectWithSite, (void **)&spObj);
if (spObj)
{
spObj->SetSite(SAFECAST(this, IMarsPanel *)); // To connect our QueryService
}
}
m_spMarsDocument->MarsWindow()->NotifyHost(MARSHOST_ON_PANEL_INIT, SAFECAST(this, IMarsPanel *), 0);
if(pLayout->szUrl[0])
{
m_bstrStartUrl = pLayout->szUrl;
}
if(!(m_dwFlags & PANEL_FLAG_ONDEMAND))
{
CreateControl();
}
if(m_dwFlags & PANEL_FLAG_VISIBLE)
{
OnLayoutChange();
}
return S_OK;
}
//------------------------------------------------------------------------------
DELAY_LOAD_NAME_HRESULT(g_hinstBorg, mshtml, BorgDllGetClassObject, DllGetClassObject,
(REFCLSID rclsid, REFIID riid, LPVOID* ppv),
(rclsid, riid, ppv));
HRESULT CMarsPanel::CreateControlObject()
{
ATLASSERT(!m_fControlCreated);
CComPtr<IAxWinHostWindow> spHost;
HRESULT hr = m_Content.QueryHost(&spHost);
if (SUCCEEDED(hr))
{
if(IsWebBrowser())
{
hr = spHost->CreateControl(wszCLSID_WebBrowser, m_Content, 0);
}
else if(IsCustomControl())
{
hr = spHost->CreateControl(m_bstrStartUrl, m_Content, 0);
}
else
{
if (IsTrusted())
{
CComPtr<IClassFactory> spCf;
hr = BorgDllGetClassObject(CLSID_HTADoc, IID_IClassFactory, (void **)&spCf);
if (SUCCEEDED(hr))
{
CComPtr<IUnknown> spUnk;
hr = spCf->CreateInstance(NULL, IID_IUnknown, (void **)&spUnk);
if (SUCCEEDED(hr))
{
hr = spHost->AttachControl(spUnk, m_Content);
}
}
}
else
{
hr = spHost->CreateControl(wszCLSID_HTMLDocument, m_Content, 0);
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// Internal function called when panel is first made visible
HRESULT CMarsPanel::CreateControl()
{
HRESULT hr = S_FALSE;
if(!m_fControlCreated)
{
// Create WebBrowser or Trident and navigate to default url
if (SUCCEEDED(CreateControlObject()))
{
m_fControlCreated = TRUE;
if(IsWebBrowser())
{
CComPtr<IUnknown> spUnk;
if (SUCCEEDED(m_Content.QueryControl(IID_IUnknown, (void **)&spUnk)))
{
m_BrowserEvents.Connect(spUnk, TRUE);
// get the browserservice that we will intercept to update the travel log
// only if this is a WebBrowser and not a Popup
if (!m_spBrowserService)
{
HRESULT hrQS = IUnknown_QueryService(spUnk, SID_STopFrameBrowser,
IID_IBrowserService,
(void **)&m_spBrowserService);
if (FAILED(hrQS))
{
ATLASSERT(!m_spBrowserService);
}
}
CComPtr<IOleCommandTarget> spCommandTarget;
if (SUCCEEDED(IUnknown_QueryService(spUnk, SID_STopFrameBrowser, IID_IOleCommandTarget, (void **)&spCommandTarget)))
{
VARIANT var;
var.vt = VT_BOOL;
var.boolVal = TRUE;
spCommandTarget->Exec(&CGID_InternetExplorer,
IECMDID_SET_INVOKE_DEFAULT_BROWSER_ON_NEW_WINDOW,
0,
&var,
NULL);
}
}
}
else if(IsCustomControl())
{
}
else
{
ConnectCompletionAdviser();
}
if(IsTrusted())
{
m_Content.SetExternalDispatch(&m_MarsExternal);
}
if (m_bstrStartUrl)
{
ATLASSERT(m_bstrStartUrl[0]);
NavigateURL(m_bstrStartUrl, FALSE);
m_bstrStartUrl.Empty();
}
m_spMarsDocument->MarsWindow()->NotifyHost(MARSHOST_ON_PANEL_CONTROL_CREATE, SAFECAST(this, IMarsPanel *), 0);
hr = S_OK;
}
else
{
hr = E_FAIL;
}
}
return hr;
}
//------------------------------------------------------------------------------
// This returns void because it calls a script method that might return
// S_FALSE with no URL, so we should force callers to check the BSTR
//
// rbstrUrl = document.location.href
//
void CMarsPanel::GetUrl(CComBSTR& rbstrUrl)
{
CComPtr<IHTMLDocument2> spDoc2;
GetDoc2FromAxWindow(&m_Content, &spDoc2);
if (spDoc2)
{
CComPtr<IHTMLLocation> spLoc;
spDoc2->get_location(&spLoc);
if (spLoc)
{
spLoc->get_href(&rbstrUrl);
}
}
}
//------------------------------------------------------------------------------
HRESULT CMarsPanel::NavigateMk(IMoniker *pmk)
{
HRESULT hr = E_FAIL;
if (VerifyNotPassive())
{
CComPtr<IPersistMoniker> spPersistMk;
if (SUCCEEDED(m_Content.QueryControl(IID_IPersistMoniker, (void **)&spPersistMk)))
{
m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects((IDispatch *)this);
hr = spPersistMk->Load(FALSE, pmk, NULL, 0);
}
else
{
// NavigateMk: QueryControl failed -- the most likely reason for this is that
// you don't have CLSID_HTADocument registered -- upgrade your IE bits
ATLASSERT(FALSE);
// Don't just hang the UI
m_lReadyState = READYSTATE_COMPLETE;
}
}
return hr;
}
//------------------------------------------------------------------------------
HRESULT CMarsPanel::NavigateURL(LPCWSTR lpszURL, BOOL fForceLoad)
{
HRESULT hr = E_FAIL;
if (VerifyNotPassive())
{
CreateControl();
BOOL fIgnoreNavigate = FALSE;
#ifdef BLOCK_PANEL_RENAVIGATES
if (!fForceLoad && IsTrusted() && !IsContentInvalid())
{
CComBSTR sbstrCurrentUrl;
GetUrl(sbstrCurrentUrl);
if (sbstrCurrentUrl && (0 == StrCmpIW(sbstrCurrentUrl, lpszURL)))
{
fIgnoreNavigate = TRUE;
hr = S_FALSE;
}
}
#endif
if(!fIgnoreNavigate)
{
if(IsWebBrowser())
{
CComPtr<IWebBrowser2> spWebBrowser2;
if (SUCCEEDED(m_Content.QueryControl(IID_IWebBrowser2, (void **)&spWebBrowser2)))
{
CComVariant varEmpty;
CComVariant varURL(lpszURL);
m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects((IDispatch *)this);
hr = spWebBrowser2->Navigate2(&varURL, &varEmpty, &varEmpty, &varEmpty, &varEmpty);
}
}
else if(IsCustomControl())
{
}
else
{
CComPtr<IMoniker> spMkUrl;
if (SUCCEEDED(CreateURLMoniker(NULL, lpszURL, &spMkUrl)) && spMkUrl)
{
hr = NavigateMk(spMkUrl);
}
}
}
if (SUCCEEDED(hr))
{
m_fContentInvalid = FALSE;
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::navigate
//
HRESULT CMarsPanel::navigate(VARIANT varTarget, VARIANT varForceLoad)
{
HRESULT hr = S_FALSE;
if (API_IsValidVariant(varTarget) && VerifyNotPassive(&hr))
{
CComBSTR strPath;
if (SUCCEEDED(MarsVariantToPath(varTarget, strPath)))
{
if (!PathIsURLW(strPath) && PathIsURLFileW(strPath))
{
// handle navigate to .url shortcut
CComPtr<IDispatch> spDisp;
CreateControl();
if (SUCCEEDED(m_Content.QueryControl(&spDisp)))
{
if (SUCCEEDED(MarsNavigateShortcut(spDisp, strPath)))
{
m_spMarsDocument->MarsWindow()->ReleaseOwnedObjects((IDispatch *)this);
hr = S_OK;
}
}
}
else
{
// handle navigate to URL
BOOL fForceLoad;
if (varForceLoad.vt == VT_BOOL)
{
// the optional param was specified
fForceLoad = varForceLoad.boolVal;
}
else
{
fForceLoad = FALSE;
}
if (SUCCEEDED(NavigateURL(strPath, fForceLoad)))
{
hr = S_OK;
}
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanel::refresh
//
HRESULT CMarsPanel::refresh(void)
{
m_fInRefresh = TRUE;
execMshtml(IDM_REFRESH, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
m_fInRefresh = FALSE;
m_fContentInvalid = FALSE;
return S_OK;
}
//------------------------------------------------------------------------------
void CMarsPanel::OnLayoutChange()
{
ATLASSERT(!IsPassive());
if (!m_fVisible && !m_Content.IsWindowVisible())
{
// We're not even visible. Nothing to do.
return;
}
// Create content if it's not already created
CreateControl();
// Redraw entire Mars window
m_spPanelCollection->Layout();
}
//------------------------------------------------------------------------------
void CMarsPanel::MakeVisible(VARIANT_BOOL bVisible, VARIANT_BOOL bForce)
{
ATLASSERT(!IsPassive());
BOOL fVisible = m_Content.IsWindowVisible();
if (bForce || (!!fVisible != !!bVisible))
{
m_Content.ShowWindow((bVisible) ? SW_SHOW : SW_HIDE);
}
}
//------------------------------------------------------------------------------
void CMarsPanel::OnWindowPosChanging(WINDOWPOS *pWindowPos)
{
if (!IsPassive() && !m_spPanelCollection->IsLayoutLocked())
{
if (pWindowPos->x < 0)
{
pWindowPos->x = 0;
}
if (pWindowPos->y < 0)
{
pWindowPos->y = 0;
}
}
}
//------------------------------------------------------------------------------
inline void DimChange(long& lMember, int iVal, BOOL& bChanged)
{
if (lMember != iVal)
{
lMember = iVal;
bChanged = TRUE;
}
}
//------------------------------------------------------------------------------
void CMarsPanel::OnWindowPosChanged(WINDOWPOS *pWindowPos)
{
if(!IsPassive() && !m_spPanelCollection->IsLayoutLocked())
{
BOOL bChanged = FALSE;
switch(m_Position)
{
case PANEL_POPUP:
if(!(pWindowPos->flags & SWP_NOMOVE)) DimChange(m_lX , pWindowPos->x , bChanged);
if(!(pWindowPos->flags & SWP_NOMOVE)) DimChange(m_lY , pWindowPos->y , bChanged);
if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lWidth , pWindowPos->cx, bChanged);
if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lHeight, pWindowPos->cy, bChanged);
break;
case PANEL_BOTTOM:
case PANEL_TOP:
if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lHeight, pWindowPos->cy, bChanged);
break;
case PANEL_LEFT:
case PANEL_RIGHT:
if(!(pWindowPos->flags & SWP_NOSIZE)) DimChange(m_lWidth, pWindowPos->cx, bChanged);
break;
}
if(bChanged)
{
OnLayoutChange();
}
}
}
//------------------------------------------------------------------------------
void CMarsPanel::GetMinMaxInfo( POINT& ptMin, POINT& ptMax )
{
long lWidth = m_lWidth;
long lHeight = m_lHeight;
long lMinWidth;
long lMinHeight;
long lMaxWidth;
long lMaxHeight;
if(!IsAutoSizing())
{
lMinWidth = m_lMinWidth;
lMinHeight = m_lMinHeight;
lMaxWidth = m_lMaxWidth;
lMaxHeight = m_lMaxHeight;
}
else
{
ComputeDimensionsOfContent( &lMinWidth, &lMinHeight );
if(m_lMinWidth != -1 && lMinWidth < m_lMinWidth ) lMinWidth = m_lMinWidth;
if(m_lMinHeight != -1 && lMinHeight < m_lMinHeight) lMinHeight = m_lMinHeight;
lMaxWidth = m_lMaxWidth;
lMaxHeight = m_lMaxHeight;
if(lMinWidth > lWidth ) lWidth = lMinWidth;
if(lMinHeight > lHeight) lHeight = lMinHeight;
}
switch(m_Position)
{
case PANEL_BOTTOM:
case PANEL_TOP :
if(lMinHeight < 0) lMinHeight = lHeight;
if(lMaxHeight < 0) lMaxHeight = lHeight;
break;
case PANEL_LEFT :
case PANEL_RIGHT:
if(lMinWidth < 0) lMinWidth = lWidth;
if(lMaxWidth < 0) lMaxWidth = lWidth;
break;
}
ptMin.x = lMinWidth;
ptMin.y = lMinHeight;
ptMax.x = lMaxWidth;
ptMax.y = lMaxHeight;
}
bool CMarsPanel::CanLayout( RECT& rcClient, POINT& ptDiff )
{
ptDiff.x = 0;
ptDiff.y = 0;
if(IsVisible())
{
RECT rcClient2;
POINT ptMin;
POINT ptMax;
long lWidth;
long lHeight;
GetRect ( &rcClient, &rcClient2 );
GetMinMaxInfo( ptMin , ptMax );
lWidth = rcClient2.right - rcClient2.left;
lHeight = rcClient2.bottom - rcClient2.top;
if(ptMin.x >= 0 && lWidth < ptMin.x) ptDiff.x -= (lWidth - ptMin.x);
if(ptMax.x >= 0 && lWidth > ptMax.x) ptDiff.x -= (lWidth - ptMax.x);
if(ptMin.y >= 0 && lHeight < ptMin.y) ptDiff.y -= (lHeight - ptMin.y);
if(ptMax.y >= 0 && lHeight > ptMax.y) ptDiff.y -= (lHeight - ptMax.y);
}
return ptDiff.x == 0 && ptDiff.y == 0;
}
//------------------------------------------------------------------------------
// S_FALSE : We used up all remaining client area
// E_INVALIDARG : *prcClient was empty, so we are hidden
HRESULT CMarsPanel::Layout( RECT *prcClient )
{
ATLASSERT(prcClient);
ATLASSERT(!IsPassive());
RECT rcMyClient;
HRESULT hr = S_OK;
if (m_fVisible && !IsRectEmpty(prcClient))
{
hr = GetRect(prcClient, &rcMyClient);
// Optimize out the case that the rect is the same as we already have. This
// is pretty common, and Windows doesn't optimize it out.
RECT rcCurrent;
GetMyClientRectInParentCoords(&rcCurrent);
if(memcmp( &rcCurrent, &rcMyClient, sizeof(RECT) ))
{
m_Content.MoveWindow( &rcMyClient, TRUE );
}
if (IsPopup())
{
// Bring popup windows to top
m_Content.SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE);
}
MakeVisible(VARIANT_TRUE, VARIANT_FALSE);
}
else
{
if (m_fVisible)
{
// We wanted to be visible but had no remaining client area
hr = E_INVALIDARG;
}
MakeVisible(VARIANT_FALSE, VARIANT_FALSE);
}
return hr;
}
//------------------------------------------------------------------------------
// IPropertyNotifySink::OnChanged
//
STDMETHODIMP CMarsPanel::OnChanged(DISPID dispID)
{
if (DISPID_READYSTATE == dispID)
{
VARIANT vResult = {0};
EXCEPINFO excepInfo;
UINT uArgErr;
DISPPARAMS dp = {NULL, NULL, 0, 0};
CComPtr<IHTMLDocument2> spDocument;
if (SUCCEEDED(m_Content.QueryControl(IID_IHTMLDocument2, (void **)&spDocument))
&& SUCCEEDED(spDocument->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo,
&uArgErr)))
{
m_lReadyState = (READYSTATE)V_I4(&vResult);
switch (m_lReadyState)
{
case READYSTATE_UNINITIALIZED: //= 0,
break;
case READYSTATE_LOADING: //= 1,
break;
case READYSTATE_LOADED: //= 2,
break;
case READYSTATE_INTERACTIVE: //= 3,
break;
case READYSTATE_COMPLETE: //= 4
if (IsAutoSizing())
{
OnLayoutChange();
}
m_spMarsDocument->GetPlaces()->OnPanelReady();
break;
}
}
}
return NOERROR;
}
//------------------------------------------------------------------------------
void CMarsPanel::ConnectCompletionAdviser()
{
if (!m_dwCookie)
{
CComPtr<IConnectionPointContainer> spICPC;
if (SUCCEEDED(m_Content.QueryControl(IID_IConnectionPointContainer, (void **)&spICPC)))
{
CComPtr<IConnectionPoint> spCP;
if (spICPC && SUCCEEDED(spICPC->FindConnectionPoint(IID_IPropertyNotifySink, &spCP)))
{
spCP->Advise((LPUNKNOWN)(IPropertyNotifySink*)this, &m_dwCookie);
ATLASSERT(m_dwCookie);
}
}
}
}
//------------------------------------------------------------------------------
void CMarsPanel::DisconnectCompletionAdviser()
{
if (m_dwCookie)
{
CComPtr<IConnectionPointContainer> spICPC;
if (SUCCEEDED(m_Content.QueryControl(IID_IConnectionPointContainer, (void **)&spICPC)))
{
CComPtr<IConnectionPoint> spCP;
if (spICPC && SUCCEEDED(spICPC->FindConnectionPoint(IID_IPropertyNotifySink, &spCP)))
{
spCP->Unadvise(m_dwCookie);
m_dwCookie = 0;
}
}
}
}
//------------------------------------------------------------------------------
// Given some content, we're going to compute its dimensions and use those.
//
void CMarsPanel::ComputeDimensionsOfContent(long *plWidth, long *plHeight)
{
ATLASSERT(plWidth && plHeight);
ATLASSERT(!IsPassive());
*plWidth = -1;
*plHeight = -1;
if(!IsWebBrowser() && IsAutoSizing())
{
CComPtr<IHTMLDocument2> spDocument;
if(SUCCEEDED(m_Content.QueryControl(IID_IHTMLDocument2, (void **)&spDocument)))
{
CComPtr<IHTMLElement> spBody;
if(spDocument)
{
spDocument->get_body( &spBody );
}
BOOL fScrollBar = FALSE;
BOOL fHeight = (m_Position == PANEL_BOTTOM) ||
(m_Position == PANEL_TOP ) ||
(m_Position == PANEL_POPUP );
BOOL fWidth = (m_Position == PANEL_LEFT ) ||
(m_Position == PANEL_RIGHT) ||
(m_Position == PANEL_POPUP);
CComQIPtr<IHTMLElement2> spBody2(spBody);
if(spBody2 && fHeight)
{
LONG lScrollHeight = 0; spBody2->get_scrollHeight( &lScrollHeight );
if(m_lMaxHeight >= 0 && lScrollHeight > m_lMaxHeight)
{
*plHeight = m_lMaxHeight;
fScrollBar = TRUE;
}
else
{
*plHeight = lScrollHeight;
}
}
if(spBody2 && fWidth)
{
LONG lScrollWidth = 0; spBody2->get_scrollWidth( &lScrollWidth );
if(m_lMaxWidth >= 0 && lScrollWidth > m_lMaxWidth)
{
*plWidth = m_lMaxWidth;
fScrollBar = TRUE;
}
else
{
*plWidth = lScrollWidth;
}
}
CComQIPtr<IHTMLBodyElement> spBody3(spBody);
if(spBody3)
{
spBody3->put_scroll( CComBSTR( fScrollBar ? L"yes" : L"no" ) );
}
}
}
}
//------------------------------------------------------------------------------
// Given the remaining client rect that we are allowed to use, calculate our
// own position in client coordinates, and return the remaining empty client
// rectangle
//
// S_OK : Remaining client area
// S_FALSE : No client area remaining
HRESULT CMarsPanel::GetRect(RECT *prcClient, RECT *prcMyClient)
{
ATLASSERT(!IsPassive());
HRESULT hr = S_OK;
if (!m_fVisible)
{
memset(prcMyClient, 0, sizeof(*prcMyClient));
return S_OK;
}
*prcMyClient = *prcClient;
long lWidth = m_lWidth;
long lHeight = m_lHeight;
if (IsAutoSizing())
{
long lMinWidth;
long lMinHeight;
ComputeDimensionsOfContent(&lMinWidth, &lMinHeight);
if(lMinWidth > lWidth ) lWidth = lMinWidth;
if(lMinHeight > lHeight) lHeight = lMinHeight;
}
if(m_lMinWidth >= 0 && lWidth < m_lMinWidth ) lWidth = m_lMinWidth;
if(m_lMinHeight >= 0 && lHeight < m_lMinHeight) lHeight = m_lMinHeight;
switch (m_Position)
{
case PANEL_POPUP:
// Special case: we exist on top of the other panels.
if (m_lX < 0)
{
prcMyClient->right = prcClient->right + 1 + m_lX;
prcMyClient->left = prcMyClient->right - lWidth;
}
else
{
prcMyClient->left = prcClient->left + m_lX;
prcMyClient->right = prcMyClient->left + lWidth;
}
if (m_lY < 0)
{
prcMyClient->bottom = prcClient->bottom + 1 + m_lY;
prcMyClient->top = prcMyClient->bottom - lHeight;
}
else
{
prcMyClient->top = prcClient->top + m_lY;
prcMyClient->bottom = prcMyClient->top + lHeight;
}
break;
case PANEL_LEFT:
prcClient->left = prcMyClient->right = prcClient->left + lWidth;
if (prcClient->left > prcClient->right)
{
prcClient->left = prcMyClient->right = prcClient->right;
hr = S_FALSE;
}
break;
case PANEL_RIGHT:
prcClient->right = prcMyClient->left = prcClient->right - lWidth;
if (prcClient->right < prcClient->left)
{
prcClient->right = prcMyClient->left = prcClient->left;
hr = S_FALSE;
}
break;
case PANEL_TOP:
prcClient->top = prcMyClient->bottom = prcClient->top + lHeight;
if (prcClient->top > prcClient->bottom)
{
prcClient->top = prcMyClient->bottom = prcClient->bottom;
hr = S_FALSE;
}
break;
case PANEL_BOTTOM:
prcClient->bottom = prcMyClient->top = prcClient->bottom - lHeight;
if (prcClient->bottom < prcClient->top)
{
prcClient->bottom = prcMyClient->top = prcClient->top;
hr = S_FALSE;
}
break;
case PANEL_WINDOW:
hr = S_FALSE;
break;
default:
ATLASSERT(FALSE); // Invalid panel position.
break;
}
return hr;
}
// =========================================================
// CBrowserEvents
// =========================================================
CMarsPanel::CBrowserEvents::CBrowserEvents(CMarsPanel *pParent) :
CMarsPanelSubObject(pParent)
{
ATLASSERT(m_dwCookie == 0);
ATLASSERT(m_dwCookie2 == 0);
}
IMPLEMENT_ADDREF_RELEASE(CMarsPanel::CBrowserEvents);
//------------------------------------------------------------------------------
void CMarsPanel::CBrowserEvents::Connect(IUnknown *punk, BOOL bConnect)
{
CComPtr<IConnectionPointContainer> spCpc;
if (SUCCEEDED(punk->QueryInterface(IID_IConnectionPointContainer, (void **)&spCpc)))
{
CComPtr<IConnectionPoint> spCp;
if (SUCCEEDED(spCpc->FindConnectionPoint(DIID_DWebBrowserEvents, &spCp)))
{
if (bConnect)
{
spCp->Advise(this, &m_dwCookie);
}
else if (m_dwCookie)
{
spCp->Unadvise(m_dwCookie);
m_dwCookie = 0;
}
}
spCp.Release();
if (SUCCEEDED(spCpc->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCp)))
{
if (bConnect)
{
spCp->Advise(this, &m_dwCookie2);
}
else if (m_dwCookie2)
{
spCp->Unadvise(m_dwCookie2);
m_dwCookie2 = 0;
}
}
}
}
//------------------------------------------------------------------------------
// IUnknown::QueryInterface
//
HRESULT CMarsPanel::CBrowserEvents::QueryInterface(REFIID iid, void **ppvObject)
{
HRESULT hr;
if ((iid == IID_IUnknown) ||
(iid == IID_IDispatch))
{
AddRef();
*ppvObject = SAFECAST(this, IDispatch *);
hr = S_OK;
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
}
return hr;
}
//------------------------------------------------------------------------------
// IDispatch::Invoke
//
HRESULT CMarsPanel::CBrowserEvents::Invoke(DISPID dispidMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult,
EXCEPINFO* pexcepinfo, UINT* puArgErr)
{
HRESULT hr = S_OK;
if (VerifyNotPassive(&hr))
{
switch (dispidMember)
{
case DISPID_BEFORENAVIGATE:
case DISPID_FRAMEBEFORENAVIGATE:
case DISPID_BEFORENAVIGATE2:
{
VARIANT *pVarCancel = &pdispparams->rgvarg[0];
if (pVarCancel->vt == (VT_BOOL | VT_BYREF))
{
if (VARIANT_TRUE == *pVarCancel->pboolVal)
{
CComPtr<IHTMLDocument2> spDoc2;
GetDoc2FromAxWindow(&Parent()->m_Content, &spDoc2);
if (spDoc2)
{
VARIANT vResult = {0};
EXCEPINFO excepInfo;
UINT uArgErr;
DISPPARAMS dp = {NULL, NULL, 0, 0};
if (SUCCEEDED(spDoc2->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo, &uArgErr)))
{
Parent()->m_lReadyState = (READYSTATE)V_I4(&vResult);
}
}
}
else
{
Parent()->m_lReadyState = READYSTATE_LOADING;
}
if (READYSTATE_COMPLETE == Parent()->m_lReadyState)
{
Parent()->m_spMarsDocument->GetPlaces()->OnPanelReady();
}
}
break;
}
case DISPID_DOCUMENTCOMPLETE:
{
Parent()->m_lReadyState = READYSTATE_COMPLETE;
Parent()->m_spMarsDocument->GetPlaces()->OnPanelReady();
break;
}
} // switch(dispidMember)
}
return hr;
}
//------------------------------------------------------------------------------
STDMETHODIMP CMarsPanel::TranslateAccelerator(MSG *pMsg, DWORD grfModifiers)
{
HRESULT hr;
ATLASSERT(!m_fTabCycle);
if (IsVK_TABCycler(pMsg))
{
m_fTabCycle = TRUE;
hr = S_OK;
}
else
{
hr = S_FALSE;
}
return hr;
}
//------------------------------------------------------------------------------
STDMETHODIMP CMarsPanel::OnUIActivate()
{
ATLASSERT(!IsPassive());
m_spPanelCollection->SetActivePanel(this, TRUE);
return S_OK;
}
//------------------------------------------------------------------------------
HRESULT CMarsPanel::UIDeactivate()
{
HRESULT hr;
CComPtr<IOleInPlaceObject> spOleInPlaceObject;
if (SUCCEEDED(m_Content.QueryControl(&spOleInPlaceObject)))
{
hr = spOleInPlaceObject->UIDeactivate();
}
else
{
// What the heck else can we do?
hr = S_FALSE;
}
return hr;
}
//------------------------------------------------------------------------------
// Forwards the message to the hosted control.
void CMarsPanel::ForwardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HWND hwnd;
CComPtr<IOleWindow> spOleWindow;
// Note that we send the message directly to the window rather than use
// WM_FORWARDMSG which calls TranslateAccelerator
if (SUCCEEDED(m_Content.QueryControl(&spOleWindow)) &&
SUCCEEDED(spOleWindow->GetWindow(&hwnd)))
{
SendMessage(hwnd, uMsg, wParam, lParam);
}
}
//------------------------------------------------------------------------------
HRESULT CMarsPanel::TranslateAccelerator(MSG *pMsg)
{
ATLASSERT(!IsPassive());
HRESULT hr = S_FALSE;
BOOL fGlobal = IsGlobalKeyMessage( pMsg );
if((S_OK == SHIsChildOrSelf(m_Content.m_hWnd, pMsg->hwnd)) || fGlobal)
{
if(m_spActiveObject && (this == m_spPanelCollection->ActivePanel()))
{
hr = m_spActiveObject->TranslateAccelerator(pMsg);
}
else
{
CComPtr<IOleInPlaceActiveObject> obj;
if(SUCCEEDED(m_Content.QueryControl( IID_IOleInPlaceActiveObject, (void **)&obj )))
{
hr = obj->TranslateAccelerator(pMsg);
}
//
// If it's a WebBrowser, forward the accelerator directly to the Document object, otherwise accesskeys won't be resolved.
//
if(hr == S_FALSE && fGlobal)
{
CComPtr<IWebBrowser2> obj2;
if(SUCCEEDED(m_Content.QueryControl( IID_IWebBrowser2, (void **)&obj2 )))
{
CComPtr<IDispatch> disp;
if(SUCCEEDED(obj2->get_Document( &disp )) && disp)
{
CComPtr<IOleInPlaceActiveObject> obj3;
if(SUCCEEDED(disp.QueryInterface( &obj3 )))
{
hr = obj3->TranslateAccelerator(pMsg);
}
}
}
}
}
}
return hr;
}
//----------------------------------------------------------------------------
// Returns the Screen coordinates of this panel
//----------------------------------------------------------------------------
void CMarsPanel::GetMyClientRectInParentCoords(RECT *prc)
{
ATLASSERT(!IsPassive());
POINT ptParent = {0, 0}, ptMe = {0, 0}, ptOffset;
m_Content.ClientToScreen(&ptMe);
m_spMarsDocument->Window()->ClientToScreen(&ptParent);
ptOffset.x = ptMe.x - ptParent.x;
ptOffset.y = ptMe.y - ptParent.y;
m_Content.GetClientRect(prc);
OffsetRect(prc, ptOffset.x, ptOffset.y);
}
// IInternetSecurityManager
// This interface is used to override default security settings for our panels.
// These panels are trusted.
//------------------------------------------------------------------------------
// IInternetSecurityManager::SetSecuritySite
//
HRESULT CMarsPanel::SetSecuritySite(IInternetSecurityMgrSite *pSite)
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------------
// IInternetSecurityManager::GetSecuritySite
//
HRESULT CMarsPanel::GetSecuritySite(IInternetSecurityMgrSite **ppSite)
{
return E_NOTIMPL;
}
//------------------------------------------------------------------------------
// IInternetSecurityManager::MapUrlToZone
//
HRESULT CMarsPanel::MapUrlToZone(LPCWSTR pwszUrl, DWORD *pdwZone, DWORD dwFlags)
{
return INET_E_DEFAULT_ACTION;
}
//------------------------------------------------------------------------------
// IInternetSecurityManager::GetSecurityId
//
HRESULT CMarsPanel::GetSecurityId(LPCWSTR pwszUrl, BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
{
return INET_E_DEFAULT_ACTION;
}
//------------------------------------------------------------------------------
// IInternetSecurityManager::ProcessUrlAction
//
// Be as permissive as we can
//
HRESULT CMarsPanel::ProcessUrlAction(LPCWSTR pwszUrl, DWORD dwAction,
BYTE __RPC_FAR *pPolicy, DWORD cbPolicy, BYTE *pContext,
DWORD cbContext, DWORD dwFlags, DWORD dwReserved)
{
ATLASSERT(IsTrusted());
if (cbPolicy >= sizeof(DWORD))
{
*((DWORD *)pPolicy) = URLPOLICY_ALLOW;
}
return S_OK;
}
//------------------------------------------------------------------------------
// IInternetSecurityManager::QueryCustomPolicy
//
// Be as permissive as we can
//
HRESULT CMarsPanel::QueryCustomPolicy(LPCWSTR pwszUrl, REFGUID guidKey, BYTE **ppPolicy,
DWORD *pcbPolicy, BYTE *pContext, DWORD cbContext, DWORD dwReserved)
{
ATLASSERT(IsTrusted());
ATLASSERT(ppPolicy && !*ppPolicy);
ATLASSERT(pcbPolicy);
if (ppPolicy && pcbPolicy)
{
*ppPolicy = (BYTE *)CoTaskMemAlloc(sizeof(DWORD));
if (*ppPolicy)
{
*pcbPolicy = sizeof(DWORD);
*(DWORD *)*ppPolicy = URLPOLICY_ALLOW;
return S_OK;
}
}
return INET_E_DEFAULT_ACTION;
}
//------------------------------------------------------------------------------
// IInternetSecurityManager::SetZoneMapping
//
HRESULT CMarsPanel::SetZoneMapping(DWORD dwZone, LPCWSTR lpszPattern, DWORD dwFlags)
{
return INET_E_DEFAULT_ACTION;
}
//------------------------------------------------------------------------------
// IInternetSecurityManager::GetZoneMappings
//
HRESULT CMarsPanel::GetZoneMappings(DWORD dwZone, IEnumString **ppenumString, DWORD dwFlags)
{
return INET_E_DEFAULT_ACTION;
}
//------------------------------------------------------------------------------
// OnDocHostUIExec
//
// When we get an Exec from Trident on CGID_DocHostCommandHandler, we can return S_OK
// to indicate that we handled the command and Trident should take no further action
// We'll delegate the processing to script by firing events
//
// TODO: once Mars accelerators are implemented, we should just block Trident from
// taking action, and not fire any events.
//
HRESULT CMarsPanel::OnDocHostUIExec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,
VARIANTARG *pvarargIn, VARIANTARG *pvarargOut)
{
// HACK: Shdocvw/Trident sometimes tests specifically for a value like
// OLECMDERR_E_NOTSUPPORTED and will not perform an essential action
// if we return something more generic like E_FAIL.
HRESULT hr = OLECMDERR_E_NOTSUPPORTED;
if(!IsPassive() && pguidCmdGroup && (*pguidCmdGroup == CGID_DocHostCommandHandler))
{
switch (nCmdID)
{
case OLECMDID_SHOWFIND:
hr = S_OK;
break;
case IDM_NEW_TOPLEVELWINDOW:
// Shdocvw gives us this command when Ctrl+N or the localized equivalent
// is translated. We return S_OK to stop it from opening an IE window.
hr = S_OK;
break;
case IDM_REFRESH:
case IDM_REFRESH_TOP:
case IDM_REFRESH_TOP_FULL:
case IDM_REFRESH_THIS:
case IDM_REFRESH_THIS_FULL:
if(!m_fInRefresh)
{
hr = S_OK;
}
break;
case OLECMDID_SHOWSCRIPTERROR:
if(SUCCEEDED(m_spMarsDocument->MarsWindow()->NotifyHost( MARSHOST_ON_SCRIPT_ERROR, V_VT(pvarargIn) == VT_UNKNOWN ? V_UNKNOWN(pvarargIn) : NULL, 0 )))
{
V_VT (pvarargOut) = VT_BOOL;
V_BOOL(pvarargOut) = VARIANT_FALSE;
hr = S_OK;
}
break;
}
}
return hr;
}
//
// CPanelCollection implementation
//
//------------------------------------------------------------------------------
CPanelCollection::CPanelCollection(CMarsDocument *pMarsDocument)
{
m_spMarsDocument = pMarsDocument;
}
//------------------------------------------------------------------------------
CPanelCollection::~CPanelCollection()
{
ATLASSERT(GetSize() == 0);
FreePanels();
}
//------------------------------------------------------------------------------
void CPanelCollection::FreePanels()
{
for (int i=0; i<GetSize(); i++)
{
(*this)[i].PassivateAndRelease();
}
RemoveAll();
}
//------------------------------------------------------------------------------
HRESULT CPanelCollection::DoPassivate()
{
FreePanels();
m_spMarsDocument.Release();
return S_OK;
}
IMPLEMENT_ADDREF_RELEASE(CPanelCollection);
//------------------------------------------------------------------------------
// IUnknown::QueryInterface
//
STDMETHODIMP CPanelCollection::QueryInterface(REFIID iid, void **ppvObject)
{
HRESULT hr;
if (API_IsValidWritePtr(ppvObject))
{
if ((iid == IID_IUnknown) ||
(iid == IID_IDispatch) ||
(iid == IID_IMarsPanelCollection))
{
AddRef();
*ppvObject = SAFECAST(this, IMarsPanelCollection *);
hr = S_OK;
}
else
{
*ppvObject = NULL;
hr = E_NOINTERFACE;
}
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
//------------------------------------------------------------------------------
HRESULT CPanelCollection::DoEnableModeless(BOOL fEnable)
{
for (int i=0; i<GetSize(); i++)
{
(*this)[i]->DoEnableModeless(fEnable);
}
return S_OK;
}
//////////////////////////////
// IMarsPanelCollection
//------------------------------------------------------------------------------
// IMarsPanelCollection::get_panel
//
// TODO: (PaulNash, 9/19/99) This method is outdated.
// Remove once content is switched over.
//
STDMETHODIMP CPanelCollection::get_panel(LPWSTR pwszName, IMarsPanel **ppPanel)
{
CComVariant var(pwszName);
return get_item(var, ppPanel);
}
//------------------------------------------------------------------------------
// IMarsPanelCollection::addPanel
//
STDMETHODIMP CPanelCollection::addPanel(
BSTR bstrName,
VARIANT varType,
BSTR bstrStartUrl,
VARIANT varCreate,
long lFlags,
IMarsPanel **ppPanel)
{
HRESULT hr = E_INVALIDARG;
if (API_IsValidString(bstrName) &&
(VT_NULL == varType.vt || API_IsValidVariantBstr(varType)) &&
(NULL == bstrStartUrl || API_IsValidString(bstrStartUrl)) &&
(VT_NULL == varCreate.vt || API_IsValidVariantBstr(varCreate)) &&
API_IsValidFlag(lFlags, PANEL_FLAG_ALL) &&
API_IsValidWritePtr(ppPanel) )
{
*ppPanel = NULL;
if (VerifyNotPassive(&hr))
{
MarsAppDef_Panel Layout;
BSTR bstrType = VariantToBSTR( varType );
BSTR bstrCreate = VariantToBSTR( varCreate );
DWORD dwFlags = DEFAULT_PANEL_FLAGS | (DWORD)lFlags;
StringToPanelFlags( bstrType , dwFlags );
StringToPanelFlags( bstrCreate, dwFlags );
StringCchCopyW ( Layout.szName, ARRAYSIZE(Layout.szName), bstrName );
ExpandEnvironmentStringsW( bstrStartUrl , Layout.szUrl, ARRAYSIZE(Layout.szUrl ) );
Layout.dwFlags = dwFlags;
AddPanel(&Layout, NULL);
hr = get_item( CComVariant( bstrName ), ppPanel );
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanelCollection::removePanel
//
STDMETHODIMP CPanelCollection::removePanel(LPWSTR pwszName)
{
HRESULT hr = E_INVALIDARG;
if(API_IsValidString(pwszName))
{
if(VerifyNotPassive(&hr))
{
hr = S_FALSE;
for(int i=0; i<GetSize(); i++)
{
if(!StrCmpI(pwszName, (*this)[i]->GetName()))
{
BOOL fVisible = (*this)[i]->IsVisible();
(*this)[i].PassivateAndRelease();
RemoveAt(i);
if(fVisible)
{
Layout();
}
hr = S_OK;
break;
}
}
}
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanelCollection::lockLayout
//
STDMETHODIMP CPanelCollection::lockLayout()
{
HRESULT hr = S_OK;
if (VerifyNotPassive(&hr))
{
m_iLockLayout++;
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanelCollection::unlockLayout
//
STDMETHODIMP CPanelCollection::unlockLayout()
{
HRESULT hr = S_OK;
if (VerifyNotPassive(&hr))
{
if (IsLayoutLocked())
{
if (0 == --m_iLockLayout)
{
// TODO: clear lock timeout
if (m_fPendingLayout)
{
m_fPendingLayout = FALSE;
Layout();
}
}
}
}
return hr;
}
//------------------------------------------------------------------------------
void CPanelCollection::Layout()
{
if(!IsPassive())
{
if(!IsLayoutLocked())
{
RECT rcClient;
lockLayout();
m_spMarsDocument->Window()->GetClientRect( &rcClient );
if(m_spMarsDocument->MarsWindow()->CanLayout( rcClient ) == false)
{
m_spMarsDocument->MarsWindow()->FixLayout( rcClient );
}
m_fPendingLayout = FALSE;
for (int i=0; i<GetSize(); i++)
{
if (S_OK != (*this)[i]->Layout( &rcClient ))
{
// We're out of client area; won't be able to show all panels.
// Keep calling Layout for remaining panels so they can hide themselves.
}
}
ATLASSERT(!m_fPendingLayout);
unlockLayout();
}
else
{
// We'll do the layout once we get unlocked
m_fPendingLayout = TRUE;
}
}
}
//------------------------------------------------------------------------------
void CPanelCollection::SetActivePanel(CMarsPanel *pPanel, BOOL bActive)
{
if (bActive)
{
if (m_spActivePanel != pPanel)
{
if (m_spActivePanel)
{
m_spActivePanel->UIDeactivate();
m_spActivePanel.Release();
}
m_spActivePanel = pPanel;
}
}
else
{
// A panel is telling us it doesn't want to be the active
// panel anymore.
if (pPanel == m_spActivePanel)
{
m_spActivePanel->UIDeactivate();
m_spActivePanel.Release();
}
}
}
//------------------------------------------------------------------------------
// IMarsPanelCollection::get_activePanel
//
STDMETHODIMP CPanelCollection::get_activePanel(IMarsPanel **ppPanel)
{
HRESULT hr = E_INVALIDARG;
if (API_IsValidWritePtr(ppPanel))
{
*ppPanel = NULL;
if (VerifyNotPassive(&hr))
{
hr = S_OK;
*ppPanel = ActivePanel();
if (*ppPanel)
{
(*ppPanel)->AddRef();
}
}
}
return hr;
}
//------------------------------------------------------------------------------
HRESULT CPanelCollection::AddPanel( MarsAppDef_Panel* pLayout, /*optional*/ IMarsPanel **ppPanel)
{
ATLASSERT(pLayout);
ATLASSERT(!IsPassive());
HRESULT hr = E_FAIL;
if (ppPanel)
{
*ppPanel = NULL;
}
// If it's a duplicate panel name, just fail.
if (!FindPanel(pLayout->szName))
{
CComClassPtr<CMarsPanel> spPanel;
spPanel.Attach(new CMarsPanel(this, m_spMarsDocument->MarsWindow()));
if (spPanel)
{
if (Add(spPanel))
{
spPanel->Create(pLayout);
if (ppPanel)
{
hr = spPanel->QueryInterface(IID_IMarsPanel, (void **)ppPanel);
}
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
return hr;
}
//------------------------------------------------------------------------------
CMarsPanel *CPanelCollection::FindPanel(LPCWSTR pwszName)
{
ATLASSERT(!IsPassive());
CMarsPanel *pPanel = NULL;
int iLen = GetSize();
for (int i = 0; i < iLen; ++i)
{
if (!StrCmpIW(pwszName, (*this)[i]->GetName()))
{
pPanel = (*this)[i];
break;
}
}
return pPanel;
}
//------------------------------------------------------------------------------
HRESULT CPanelCollection::FindPanelIndex(CMarsPanel *pPanel, long *plIndex)
{
ATLASSERT(plIndex);
ATLASSERT(!IsPassive());
HRESULT hr = E_FAIL;
*plIndex = -1;
if (pPanel)
{
long lSize = GetSize();
for (long i = 0; i < lSize; ++i)
{
if (pPanel == (*this)[i])
{
*plIndex = i;
hr = S_OK;
break;
}
}
}
return hr;
}
//------------------------------------------------------------------------------
HRESULT CPanelCollection::InsertPanelFromTo(long lOldIndex, long lNewIndex)
{
ATLASSERT((lOldIndex >= 0) && (lOldIndex < GetSize()));
ATLASSERT(!IsPassive());
HRESULT hr = S_FALSE;
if (lNewIndex < 0)
{
lNewIndex = 0;
}
if (lNewIndex > GetSize() - 1)
{
lNewIndex = GetSize() - 1;
}
// If this is something that is done very often, we should optimize this better
// and probably not use an array
if (lOldIndex != lNewIndex)
{
CComClassPtr<CMarsPanel> spPanel = (*this)[lOldIndex];
RemoveAt(lOldIndex);
InsertAt(lNewIndex, spPanel);
hr = S_OK;
}
return hr;
}
//------------------------------------------------------------------------------
// Sets the dirty bit on all panels after a theme switch
//
void CPanelCollection::InvalidatePanels()
{
for (int i=0; i < GetSize(); i++)
{
(*this)[i]->put_contentInvalid(VARIANT_TRUE);
}
}
//------------------------------------------------------------------------------
// Called after the theme switch event has fired, to refresh any panels
// that are visible but still haven't been updated with the new theme
//
void CPanelCollection::RefreshInvalidVisiblePanels()
{
for (int i=0; i < GetSize(); i++)
{
CMarsPanel *pPanel = (*this)[i];
if (pPanel->IsVisible() && pPanel->IsContentInvalid())
{
pPanel->refresh();
}
}
}
//------------------------------------------------------------------------------
// IMarsPanelCollection::get_length
//
// standard collection method (gets instantaneous length of coll)
//
STDMETHODIMP CPanelCollection::get_length(LONG *plNumPanels)
{
HRESULT hr = E_INVALIDARG;
if (API_IsValidWritePtr(plNumPanels))
{
(*plNumPanels) = GetSize();
hr = S_OK;
}
return hr;
}
//------------------------------------------------------------------------------
// IMarsPanelCollection::get_item
//
// standard collection method (gets an theme given index or name)
//
STDMETHODIMP CPanelCollection::get_item(/*[in]*/ VARIANT varIndexOrName,
/*[out, retval]*/ IMarsPanel **ppPanel)
{
ATLASSERT(VT_BSTR == varIndexOrName.vt || VT_I4 == varIndexOrName.vt);
HRESULT hr = E_INVALIDARG;
//
// We can't use the API_IsValid varieties because they rip, and we actually don't want that.
// It's only valid to RIP on IsValidFailure if only a single type is allowed, but here we
// allow two types in the Variant, so we would only want to RIP if both are false (already
// handled by above RIP).
//
if ((IsValidVariantI4(varIndexOrName) || IsValidVariantBstr(varIndexOrName)) &&
API_IsValidWritePtr(ppPanel))
{
*ppPanel= NULL;
if (VerifyNotPassive(&hr))
{
CMarsPanel *pPanel = NULL;
if (VT_BSTR == varIndexOrName.vt)
{
pPanel = FindPanel(V_BSTR(&varIndexOrName));
if (pPanel)
{
hr = pPanel->QueryInterface(IID_IMarsPanel, (void **)ppPanel);
}
else
{
hr = S_FALSE;
}
}
else if (VT_I4 == varIndexOrName.vt)
{
long idxPanel = V_I4(&varIndexOrName);
if (idxPanel >= 0 && idxPanel < GetSize())
{
pPanel = (*this)[idxPanel];
if (pPanel)
{
hr = pPanel->QueryInterface(IID_IMarsPanel, (void **)ppPanel);
}
else
{
hr = S_FALSE;
}
}
}
else
{
// We only accept VT_BSTR and VT_I4 and we should have already
// detected any other invalid params higher up in the function.
ATLASSERT(false);
}
}
}
return hr;
} // get_item
//------------------------------------------------------------------------------
// IMarsPanelCollection::get__newEnum
// standard collection method (gets a new IEnumVARIANT)
//
STDMETHODIMP CPanelCollection::get__newEnum(/*[out, retval]*/ IUnknown **ppEnumPanels)
{
HRESULT hr = E_INVALIDARG;
if (API_IsValidWritePtr(ppEnumPanels))
{
*ppEnumPanels = NULL;
if (VerifyNotPassive(&hr))
{
// This helper takes a CMarsSimpleArray and does all
// the work of creating a CComEnum for us. Neat!
hr = CMarsComEnumVariant< CMarsPanel >::CreateFromMarsSimpleArray(*this, ppEnumPanels);
}
}
return hr;
} // get__newEnum