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
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
|