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.
1088 lines
32 KiB
1088 lines
32 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
Events.cpp
|
|
|
|
Abstract:
|
|
This file contains the implementation of the classes related to events.
|
|
|
|
Revision History:
|
|
Davide Massarenti (dmassare) 10/31/99
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <mshtmdid.h>
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifdef DEBUG
|
|
|
|
static void DEBUG_CheckReadyState()
|
|
{
|
|
CComPtr<IWebBrowser2> wb2; wb2.Attach( CPCHHelpCenterExternal::s_GLOBAL->Contents() );
|
|
tagREADYSTATE ready;
|
|
|
|
|
|
if(wb2 && SUCCEEDED(wb2->get_ReadyState( &ready )))
|
|
{
|
|
DebugLog( "#################### WEB %d\n", (int)ready );
|
|
}
|
|
}
|
|
|
|
static HRESULT DEBUG_GetReadyStateFromBrowser( IDispatch* pDisp ,
|
|
tagREADYSTATE *pVal )
|
|
{
|
|
__HCP_FUNC_ENTRY( "DEBUG_GetReadyStateFromBrowser" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<IWebBrowser2> wb;
|
|
|
|
|
|
*pVal = READYSTATE_UNINITIALIZED;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->QueryInterface( IID_IWebBrowser2, (LPVOID*)&wb ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, wb ->get_ReadyState( pVal ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT DEBUG_GetLocationFromBrowser( IDispatch* pDisp ,
|
|
BSTR *pVal )
|
|
{
|
|
__HCP_FUNC_ENTRY( "DEBUG_GetLocationFromBrowser" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<IWebBrowser2> wb;
|
|
|
|
|
|
*pVal = NULL;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pDisp->QueryInterface ( IID_IWebBrowser2, (LPVOID*)&wb ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, wb ->get_LocationURL( pVal ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT DEBUG_GetLocationFromDocument2( IHTMLDocument2* pDoc ,
|
|
BSTR *pVal )
|
|
{
|
|
__HCP_FUNC_ENTRY( "DEBUG_GetLocationFromDocument2" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<IHTMLLocation> pLoc;
|
|
|
|
|
|
*pVal = NULL;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pDoc->get_location( &pLoc )); if(pLoc == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pLoc->get_href ( pVal ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
#else
|
|
|
|
inline void DEBUG_CheckReadyState () {}
|
|
inline HRESULT DEBUG_GetReadyStateFromBrowser() { return S_OK; }
|
|
inline HRESULT DEBUG_GetLocationFromBrowser () { return S_OK; }
|
|
inline HRESULT DEBUG_GetLocationFromDocument2() { return S_OK; }
|
|
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static WCHAR s_eventNames_onBeforeNavigate [] = L"onBeforeNavigate" ;
|
|
static WCHAR s_eventNames_onNavigateComplete [] = L"onNavigateComplete" ;
|
|
|
|
static WCHAR s_eventNames_onBeforeTransition [] = L"onBeforeTransition" ;
|
|
static WCHAR s_eventNames_onTransition [] = L"onTransition" ;
|
|
|
|
static WCHAR s_eventNames_onBeforeContextSwitch[] = L"onBeforeContextSwitch";
|
|
static WCHAR s_eventNames_onContextSwitch [] = L"onContextSwitch" ;
|
|
|
|
static WCHAR s_eventNames_onPersistLoad [] = L"onPersistLoad" ;
|
|
static WCHAR s_eventNames_onPersistSave [] = L"onPersistSave" ;
|
|
static WCHAR s_eventNames_onTravelDone [] = L"onTravelDone" ;
|
|
|
|
static WCHAR s_eventNames_onShutdown [] = L"onShutdown" ;
|
|
static WCHAR s_eventNames_onPrint [] = L"onPrint" ;
|
|
|
|
static WCHAR s_eventNames_onSwitchedHelpFiles [] = L"onSwitchedHelpFiles" ;
|
|
static WCHAR s_eventNames_onFavoritesUpdate [] = L"onFavoritesUpdate" ;
|
|
static WCHAR s_eventNames_onOptionsChanged [] = L"onOptionsChanged" ;
|
|
static WCHAR s_eventNames_onCssChanged [] = L"onCssChanged" ;
|
|
|
|
static struct
|
|
{
|
|
LPCWSTR szName;
|
|
DISPID id;
|
|
}
|
|
s_lookup[] =
|
|
{
|
|
{ s_eventNames_onBeforeNavigate , DISPID_PCH_E_BEFORENAVIGATE },
|
|
{ s_eventNames_onNavigateComplete , DISPID_PCH_E_NAVIGATECOMPLETE },
|
|
|
|
{ s_eventNames_onBeforeTransition , DISPID_PCH_E_BEFORETRANSITION },
|
|
{ s_eventNames_onTransition , DISPID_PCH_E_TRANSITION },
|
|
|
|
{ s_eventNames_onBeforeContextSwitch, DISPID_PCH_E_BEFORECONTEXTSWITCH },
|
|
{ s_eventNames_onContextSwitch , DISPID_PCH_E_CONTEXTSWITCH },
|
|
|
|
{ s_eventNames_onPersistLoad , DISPID_PCH_E_PERSISTLOAD },
|
|
{ s_eventNames_onPersistSave , DISPID_PCH_E_PERSISTSAVE },
|
|
{ s_eventNames_onTravelDone , DISPID_PCH_E_TRAVELDONE },
|
|
|
|
{ s_eventNames_onShutdown , DISPID_PCH_E_SHUTDOWN },
|
|
{ s_eventNames_onPrint , DISPID_PCH_E_PRINT },
|
|
|
|
{ s_eventNames_onSwitchedHelpFiles , DISPID_PCH_E_SWITCHEDHELPFILES },
|
|
{ s_eventNames_onFavoritesUpdate , DISPID_PCH_E_FAVORITESUPDATE },
|
|
{ s_eventNames_onOptionsChanged , DISPID_PCH_E_OPTIONSCHANGED },
|
|
{ s_eventNames_onCssChanged , DISPID_PCH_E_CSSCHANGED },
|
|
};
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool CPCHEvents::EventRegistration::operator==( /*[in]*/ const long lCookie ) const { return m_lCookie == lCookie ; }
|
|
bool CPCHEvents::EventRegistration::operator< ( /*[in]*/ const long lPriority ) const { return m_lPriority < lPriority; }
|
|
|
|
CPCHEvents::CPCHEvents()
|
|
{
|
|
m_parent = NULL; // CPCHHelpCenterExternal* m_parent;
|
|
// List m_lstEvents;
|
|
// List m_lstEvents_Staging;
|
|
m_lLastCookie = 0; // long m_lLastCookie;
|
|
}
|
|
|
|
CPCHEvents::~CPCHEvents()
|
|
{
|
|
Passivate();
|
|
}
|
|
|
|
void CPCHEvents::Initialize( /*[in]*/ CPCHHelpCenterExternal* parent )
|
|
{
|
|
m_parent = parent;
|
|
}
|
|
|
|
void CPCHEvents::Passivate()
|
|
{
|
|
//
|
|
// We don't remove the item from the main list, only FireEvent is allowed to change that list!
|
|
//
|
|
for(Iter it=m_lstEvents.begin(); it!=m_lstEvents.end(); it++)
|
|
{
|
|
it->m_fnCallback.Release();
|
|
}
|
|
|
|
m_lstEvents_Staging.clear();
|
|
|
|
m_parent = NULL;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT CPCHEvents::RegisterEvents( /*[in]*/ long id ,
|
|
/*[in]*/ long pri ,
|
|
/*[in]*/ IDispatch* function ,
|
|
/*[out,retval]*/ long *cookie )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHEvents::RegisterEvents" );
|
|
|
|
HRESULT hr;
|
|
Iter it;
|
|
|
|
|
|
if(id != -1) // Special case, used only internally, to pass the ID of the event through the Invoke method call.
|
|
{
|
|
if(CPCHEvents::ReverseLookup( id ) == NULL)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
|
|
}
|
|
}
|
|
|
|
|
|
it = m_lstEvents_Staging.insert( m_lstEvents_Staging.end() ); // This line creates a new item!!
|
|
|
|
it->m_lCookie = ++m_lLastCookie; // long m_lCookie;
|
|
it->m_id = id; // DISPID m_id;
|
|
it->m_lPriority = pri; // long m_lPriority;
|
|
it->m_fnCallback = function; // MPC::CComPtrThreadNeutral<IDispatch> m_fnCallback;
|
|
|
|
if(cookie) *cookie = it->m_lCookie;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHEvents::RegisterEvents( /*[in]*/ BSTR bstrID ,
|
|
/*[in]*/ long pri ,
|
|
/*[in]*/ IDispatch* function ,
|
|
/*[out,retval]*/ long *cookie )
|
|
{
|
|
return RegisterEvents( bstrID ? CPCHEvents::Lookup( bstrID ) : -1, pri, function, cookie );
|
|
}
|
|
|
|
HRESULT CPCHEvents::UnregisterEvents( /*[in]*/ long cookie )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHEvents::UnregisterEvents" );
|
|
|
|
HRESULT hr;
|
|
Iter it;
|
|
|
|
|
|
//
|
|
// We don't remove the item from the main list, only FireEvent is allowed to change that list!
|
|
//
|
|
it = std::find( m_lstEvents.begin(), m_lstEvents.end(), cookie );
|
|
if(it != m_lstEvents.end())
|
|
{
|
|
it->m_fnCallback.Release();
|
|
}
|
|
|
|
|
|
it = std::find( m_lstEvents_Staging.begin(), m_lstEvents_Staging.end(), cookie );
|
|
if(it != m_lstEvents_Staging.end())
|
|
{
|
|
m_lstEvents_Staging.erase( it );
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT CPCHEvents::FireEvent( /*[in]*/ CPCHEvent* eventObj )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent" );
|
|
|
|
HRESULT hr;
|
|
|
|
if(m_parent)
|
|
{
|
|
Iter it;
|
|
Iter itStaging;
|
|
DISPID id = eventObj->m_idAction;
|
|
CComVariant vEvent = eventObj;
|
|
CPCHHelpSession* hs = m_parent->HelpSession();
|
|
|
|
|
|
eventObj->m_hsiCurrentContext = hs->Current();
|
|
if(eventObj->m_hsiCurrentContext)
|
|
{
|
|
eventObj->m_hsiPreviousContext = eventObj->m_hsiCurrentContext->Previous();
|
|
}
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_EVENTS_OUT, L"CPCHHelpCenterExternal::FireEvent: %s - URL: %s - Frame: %s - Panel: %s",
|
|
CPCHEvents::ReverseLookup( id ),
|
|
SAFEBSTR( eventObj->m_bstrURL ),
|
|
SAFEBSTR( eventObj->m_bstrFrame ),
|
|
SAFEBSTR( eventObj->m_bstrPanel ) );
|
|
|
|
DebugLog( L"%%%%%%%%%%%%%%%%%%%% EVENT %s - URL: %s - Frame: %s - Panel: %s\n",
|
|
CPCHEvents::ReverseLookup( id ),
|
|
SAFEBSTR( eventObj->m_bstrURL ),
|
|
SAFEBSTR( eventObj->m_bstrFrame ),
|
|
SAFEBSTR( eventObj->m_bstrPanel ) );
|
|
|
|
|
|
//
|
|
// Merge staging list into main list.
|
|
//
|
|
for(itStaging=m_lstEvents_Staging.begin(); itStaging!=m_lstEvents_Staging.end(); itStaging++)
|
|
{
|
|
//
|
|
// Insert in priority order.
|
|
//
|
|
for(it=m_lstEvents.begin(); it!=m_lstEvents.end(); it++)
|
|
{
|
|
if(*it < itStaging->m_lPriority) break;
|
|
}
|
|
|
|
m_lstEvents.insert( it, *itStaging );
|
|
}
|
|
m_lstEvents_Staging.clear();
|
|
|
|
|
|
//
|
|
// Dispatch the event to all the sinks registered for it.
|
|
//
|
|
for(it=m_lstEvents.begin(); it!=m_lstEvents.end(); )
|
|
{
|
|
if(it->m_id == -1 || // Listen to all the events...
|
|
it->m_id == id )
|
|
{
|
|
CComPtr<IDispatch> pPtr = it->m_fnCallback;
|
|
CComDispatchDriver pDisp = pPtr;
|
|
|
|
if(pDisp)
|
|
{
|
|
if(SUCCEEDED(pDisp.Invoke1( it->m_id == -1 ? id : (DISPID)0, &vEvent )))
|
|
{
|
|
VARIANT_BOOL fCancel;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, eventObj->get_Cancel( &fCancel ));
|
|
|
|
if(fCancel == VARIANT_TRUE) break;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The script is no more valid, prepare to release it.
|
|
//
|
|
it->m_fnCallback.Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!m_parent) break; // We have been passivated...
|
|
|
|
if(!it->m_fnCallback)
|
|
{
|
|
m_lstEvents.erase( it++ );
|
|
}
|
|
else
|
|
{
|
|
it++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!m_parent) // We have been passivated...
|
|
{
|
|
m_lstEvents .clear();
|
|
m_lstEvents_Staging.clear();
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CPCHEvents::FireEvent_Generic( /*[in]*/ DISPID id ,
|
|
/*[out]*/ VARIANT_BOOL *Cancel )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_Generic" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHEvent> obj;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
|
|
|
|
|
|
obj->m_idAction = id;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
|
|
|
|
if(Cancel) *Cancel = obj->m_fCancel;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
|
|
HRESULT CPCHEvents::FireEvent_BeforeNavigate( /*[in]*/ BSTR bstrURL ,
|
|
/*[in]*/ BSTR bstrFrame ,
|
|
/*[in]*/ HscPanel idPanel ,
|
|
/*[out]*/ VARIANT_BOOL *Cancel )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_BeforeNavigate" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHEvent> obj;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
|
|
|
|
|
|
obj->m_idAction = DISPID_PCH_E_BEFORENAVIGATE;
|
|
obj->m_bstrURL = bstrURL;
|
|
obj->m_bstrFrame = bstrFrame;
|
|
obj->m_bstrPanel = m_parent->PanelName( idPanel );
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
|
|
|
|
if(Cancel) *Cancel = obj->m_fCancel;
|
|
|
|
hr = S_OK;
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHEvents::FireEvent_NavigateComplete( /*[in]*/ BSTR bstrURL ,
|
|
/*[in]*/ HscPanel idPanel ,
|
|
/*[out]*/ VARIANT_BOOL *Cancel )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHHelpCenterExternal::FireEvent_NavigateComplete" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHEvent> obj;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
|
|
|
|
|
|
obj->m_idAction = DISPID_PCH_E_NAVIGATECOMPLETE;
|
|
obj->m_bstrURL = bstrURL;
|
|
obj->m_bstrPanel = m_parent->PanelName( idPanel );
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
|
|
|
|
if(Cancel) *Cancel = obj->m_fCancel;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHEvents::FireEvent_BeforeTransition( /*[in]*/ BSTR bstrPlace ,
|
|
/*[out]*/ VARIANT_BOOL *Cancel )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_BeforeTransition" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHEvent> obj;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
|
|
|
|
|
|
obj->m_idAction = DISPID_PCH_E_BEFORETRANSITION;
|
|
obj->m_bstrPlace = bstrPlace;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
|
|
|
|
if(Cancel) *Cancel = obj->m_fCancel;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHEvents::FireEvent_Transition( /*[in]*/ BSTR bstrPlace )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_Transition" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHEvent> obj;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
|
|
|
|
|
|
obj->m_idAction = DISPID_PCH_E_TRANSITION;
|
|
obj->m_bstrPlace = bstrPlace;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHEvents::FireEvent_BeforeContextSwitch( /*[in ]*/ HscContext iVal ,
|
|
/*[in ]*/ BSTR bstrInfo ,
|
|
/*[in ]*/ BSTR bstrURL ,
|
|
/*[out]*/ VARIANT_BOOL *Cancel )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHEvents::FireEvent_BeforeContextSwitch" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<CPCHEvent> obj;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
|
|
|
|
|
|
obj->m_idAction = DISPID_PCH_E_BEFORECONTEXTSWITCH;
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->HelpSession()->RegisterContextSwitch( iVal, bstrInfo, bstrURL, &obj->m_hsiNextContext ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Events().FireEvent( obj ));
|
|
|
|
if(Cancel) *Cancel = obj->m_fCancel;
|
|
|
|
hr = S_OK;
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT CPCHEvents::FireEvent_ContextSwitch ( ) { return FireEvent_Generic( DISPID_PCH_E_CONTEXTSWITCH ); }
|
|
HRESULT CPCHEvents::FireEvent_PersistLoad ( ) { return FireEvent_Generic( DISPID_PCH_E_PERSISTLOAD ); }
|
|
HRESULT CPCHEvents::FireEvent_PersistSave ( ) { return FireEvent_Generic( DISPID_PCH_E_PERSISTSAVE ); }
|
|
HRESULT CPCHEvents::FireEvent_TravelDone ( ) { return FireEvent_Generic( DISPID_PCH_E_TRAVELDONE ); }
|
|
HRESULT CPCHEvents::FireEvent_Shutdown ( VARIANT_BOOL *Cancel ) { return FireEvent_Generic( DISPID_PCH_E_SHUTDOWN , Cancel ); }
|
|
HRESULT CPCHEvents::FireEvent_Print ( VARIANT_BOOL *Cancel ) { return FireEvent_Generic( DISPID_PCH_E_PRINT , Cancel ); }
|
|
|
|
HRESULT CPCHEvents::FireEvent_SwitchedHelpFiles( ) { return FireEvent_Generic( DISPID_PCH_E_SWITCHEDHELPFILES ); }
|
|
HRESULT CPCHEvents::FireEvent_FavoritesUpdate ( ) { return FireEvent_Generic( DISPID_PCH_E_FAVORITESUPDATE ); }
|
|
HRESULT CPCHEvents::FireEvent_OptionsChanged ( ) { return FireEvent_Generic( DISPID_PCH_E_OPTIONSCHANGED ); }
|
|
HRESULT CPCHEvents::FireEvent_CssChanged ( ) { return FireEvent_Generic( DISPID_PCH_E_CSSCHANGED ); }
|
|
|
|
|
|
DISPID CPCHEvents::Lookup( LPCWSTR szName )
|
|
{
|
|
if(szName)
|
|
{
|
|
for(int i = 0; i<ARRAYSIZE(s_lookup); i++)
|
|
{
|
|
if(!_wcsicmp( s_lookup[i].szName, szName )) return s_lookup[i].id;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
LPCWSTR CPCHEvents::ReverseLookup( DISPID idEvent )
|
|
{
|
|
for(int i = 0; i<ARRAYSIZE(s_lookup); i++)
|
|
{
|
|
if(s_lookup[i].id == idEvent) return s_lookup[i].szName;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CPCHEvent::CPCHEvent()
|
|
{
|
|
// DISPID m_idAction;
|
|
m_fCancel = VARIANT_FALSE; // VARIANT_BOOL m_fCancel;
|
|
//
|
|
// CComBSTR m_bstrURL;
|
|
// CComBSTR m_bstrFrame;
|
|
// CComBSTR m_bstrPanel;
|
|
// CComBSTR m_bstrPlace;
|
|
// CComBSTR m_bstrContextData;
|
|
//
|
|
// CComPtr<CPCHHelpSessionItem> m_hsiCurrentContext;
|
|
// CComPtr<CPCHHelpSessionItem> m_hsiPreviousContext;
|
|
}
|
|
|
|
CPCHEvent::~CPCHEvent()
|
|
{
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
STDMETHODIMP CPCHEvent::get_Action( /*[out, retval]*/ BSTR *pVal )
|
|
{
|
|
return MPC::GetBSTR( CPCHEvents::ReverseLookup( m_idAction ), pVal );
|
|
}
|
|
|
|
////////////////////
|
|
|
|
STDMETHODIMP CPCHEvent::put_Cancel( /*[in]*/ VARIANT_BOOL newVal )
|
|
{
|
|
m_fCancel = newVal;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CPCHEvent::get_Cancel( /*[out, retval]*/ VARIANT_BOOL *pVal )
|
|
{
|
|
if(pVal == NULL) return E_POINTER;
|
|
|
|
*pVal = m_fCancel;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT CPCHEvent::put_URL( /*[in]*/ BSTR newVal )
|
|
{
|
|
return MPC::PutBSTR( m_bstrURL, newVal );
|
|
}
|
|
|
|
STDMETHODIMP CPCHEvent::get_URL( /*[out, retval]*/ BSTR *pVal )
|
|
{
|
|
return MPC::GetBSTR( m_bstrURL, pVal );
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT CPCHEvent::put_Frame( /*[in]*/ BSTR newVal )
|
|
{
|
|
return MPC::PutBSTR( m_bstrFrame, newVal );
|
|
}
|
|
|
|
STDMETHODIMP CPCHEvent::get_Frame( /*[out, retval]*/ BSTR *pVal )
|
|
{
|
|
return MPC::GetBSTR( m_bstrFrame, pVal );
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT CPCHEvent::put_Panel( /*[in]*/ BSTR newVal )
|
|
{
|
|
return MPC::PutBSTR( m_bstrPanel, newVal );
|
|
}
|
|
|
|
STDMETHODIMP CPCHEvent::get_Panel( /*[out, retval]*/ BSTR *pVal )
|
|
{
|
|
return MPC::GetBSTR( m_bstrPanel, pVal );
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT CPCHEvent::put_Place( /*[in]*/ BSTR newVal )
|
|
{
|
|
return MPC::PutBSTR( m_bstrPlace, newVal );
|
|
}
|
|
|
|
STDMETHODIMP CPCHEvent::get_Place( /*[out, retval]*/ BSTR *pVal )
|
|
{
|
|
return MPC::GetBSTR( m_bstrPlace, pVal );
|
|
}
|
|
|
|
////////////////////
|
|
|
|
STDMETHODIMP CPCHEvent::get_CurrentContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal )
|
|
{
|
|
return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiCurrentContext, pVal );
|
|
}
|
|
|
|
STDMETHODIMP CPCHEvent::get_PreviousContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal )
|
|
{
|
|
return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiPreviousContext, pVal );
|
|
}
|
|
|
|
STDMETHODIMP CPCHEvent::get_NextContext( /*[out, retval]*/ IPCHHelpSessionItem* *pVal )
|
|
{
|
|
return MPC::CopyTo( (CPCHHelpSessionItem*)m_hsiNextContext, pVal );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
CPCHTimerHandle::CallbackBase::CallbackBase()
|
|
{
|
|
m_lRef = 1; // long m_lRef;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CPCHTimerHandle::CallbackBase::AddRef()
|
|
{
|
|
return ::InterlockedIncrement( &m_lRef );
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CPCHTimerHandle::CallbackBase::Release()
|
|
{
|
|
ULONG l = ::InterlockedDecrement( &m_lRef );
|
|
|
|
if(l == 0) delete this;
|
|
|
|
return l;
|
|
}
|
|
|
|
STDMETHODIMP CPCHTimerHandle::CallbackBase::QueryInterface( REFIID iid, void ** ppvObject )
|
|
{
|
|
if(ppvObject == NULL) return E_POINTER;
|
|
|
|
if(InlineIsEqualUnknown( iid ) ||
|
|
InlineIsEqualGUID ( iid, IID_ITimerSink ) )
|
|
{
|
|
*ppvObject = this; AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
*ppvObject = NULL;
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
CPCHTimerHandle::CPCHTimerHandle()
|
|
{
|
|
// CComPtr<ITimer> m_timer;
|
|
m_dwCookie = 0; // DWORD m_dwCookie;
|
|
m_callback = NULL; // CallbackBase* m_callback;
|
|
}
|
|
|
|
CPCHTimerHandle::~CPCHTimerHandle()
|
|
{
|
|
Unadvise();
|
|
}
|
|
|
|
void CPCHTimerHandle::Initialize( /*[in]*/ ITimer* timer )
|
|
{
|
|
Unadvise();
|
|
|
|
m_timer = timer;
|
|
}
|
|
|
|
HRESULT CPCHTimerHandle::Advise( /*[in]*/ CallbackBase* callback, /*[in]*/ DWORD dwWait )
|
|
{
|
|
if(!callback) return E_OUTOFMEMORY;
|
|
|
|
Unadvise();
|
|
|
|
m_callback = callback;
|
|
|
|
if(!m_timer) return E_INVALIDARG;
|
|
|
|
CComVariant vTime = (long)(dwWait + ::GetTickCount());
|
|
CComVariant vZero = 0;
|
|
|
|
return m_timer->Advise( vTime, vZero, vZero, 0, callback, &m_dwCookie );
|
|
}
|
|
|
|
void CPCHTimerHandle::Unadvise()
|
|
{
|
|
if(m_timer)
|
|
{
|
|
if(m_dwCookie)
|
|
{
|
|
m_timer->Unadvise( m_dwCookie );
|
|
|
|
m_dwCookie = 0;
|
|
}
|
|
}
|
|
|
|
if(m_callback)
|
|
{
|
|
m_callback->Detach ();
|
|
m_callback->Release();
|
|
|
|
m_callback = NULL;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
CPCHWebBrowserEvents::CPCHWebBrowserEvents()
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::CPCHWebBrowserEvents" );
|
|
|
|
m_parent = NULL; // CPCHHelpCenterExternal* m_parent;
|
|
m_idPanel = HSCPANEL_INVALID; // HscPanel m_idPanel;
|
|
//
|
|
// CComPtr<IWebBrowser2> m_pWB2;
|
|
m_fLoading = false; // bool m_fLoading;
|
|
//
|
|
// CPCHTimerHandle m_TimerDelay;
|
|
// CPCHTimerHandle m_TimerExpire;
|
|
}
|
|
|
|
CPCHWebBrowserEvents::~CPCHWebBrowserEvents()
|
|
{
|
|
Passivate();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CPCHWebBrowserEvents::NotifyStartOfNavigation( /*[in]*/ BSTR url )
|
|
{
|
|
CPCHHelpSession* hs = m_parent->HelpSession();
|
|
|
|
if(hs)
|
|
{
|
|
m_fLoading = true;
|
|
|
|
(void)hs->StartNavigation( url, m_idPanel );
|
|
}
|
|
}
|
|
|
|
void CPCHWebBrowserEvents::NotifyEndOfNavigation()
|
|
{
|
|
CPCHHelpSession* hs = m_parent->HelpSession();
|
|
|
|
m_fLoading = false;
|
|
|
|
if(hs)
|
|
{
|
|
(void)hs->CompleteNavigation( m_idPanel );
|
|
}
|
|
}
|
|
|
|
void CPCHWebBrowserEvents::NotifyStop()
|
|
{
|
|
TimerControl( TIMERMODE_STOP );
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CPCHWebBrowserEvents::Initialize( /*[in]*/ CPCHHelpCenterExternal* parent, /*[in]*/ HscPanel idPanel )
|
|
{
|
|
m_parent = parent;
|
|
m_idPanel = idPanel;
|
|
}
|
|
|
|
void CPCHWebBrowserEvents::Passivate()
|
|
{
|
|
Detach();
|
|
|
|
m_parent = NULL;
|
|
}
|
|
|
|
void CPCHWebBrowserEvents::Attach( /*[in]*/ IWebBrowser2* pWB )
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::Attach" );
|
|
|
|
|
|
Detach();
|
|
|
|
|
|
m_pWB2 = pWB;
|
|
if(m_pWB2)
|
|
{
|
|
CPCHWebBrowserEvents_DWebBrowserEvents2::DispEventAdvise( m_pWB2 );
|
|
}
|
|
|
|
m_TimerDelay .Initialize( m_parent->Timer() );
|
|
m_TimerExpire.Initialize( m_parent->Timer() );
|
|
}
|
|
|
|
void CPCHWebBrowserEvents::Detach()
|
|
{
|
|
__HCP_FUNC_ENTRY( "CPCHWebBrowserEvents::Detach" );
|
|
|
|
TimerControl( TIMERMODE_STOP );
|
|
|
|
if(m_pWB2)
|
|
{
|
|
CPCHWebBrowserEvents_DWebBrowserEvents2::DispEventUnadvise( m_pWB2 );
|
|
|
|
m_pWB2.Release();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CPCHWebBrowserEvents::TimerControl( /*[in]*/ TimerMode mode )
|
|
{
|
|
switch(mode)
|
|
{
|
|
case TIMERMODE_STOP:
|
|
m_TimerDelay .Stop();
|
|
m_TimerExpire.Stop();
|
|
break;
|
|
|
|
case TIMERMODE_RESTART:
|
|
m_TimerDelay .Stop ( );
|
|
m_TimerExpire.Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 2000 );
|
|
break;
|
|
|
|
case TIMERMODE_MORETIME:
|
|
m_TimerExpire.Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 100 );
|
|
break;
|
|
|
|
case TIMERMODE_COMPLETE:
|
|
m_TimerDelay .Start( this, (HRESULT (CPCHWebBrowserEvents::*)(VARIANT))OnTimer, 20 );
|
|
m_TimerExpire.Stop ( );
|
|
break;
|
|
}
|
|
}
|
|
|
|
HRESULT CPCHWebBrowserEvents::OnTimer( VARIANT vtimeAdvise )
|
|
{
|
|
TimerControl( TIMERMODE_STOP );
|
|
|
|
NotifyEndOfNavigation();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
void __stdcall CPCHWebBrowserEvents::BeforeNavigate2( IDispatch* pDisp ,
|
|
VARIANT* URL ,
|
|
VARIANT* Flags ,
|
|
VARIANT* TargetFrameName,
|
|
VARIANT* PostData ,
|
|
VARIANT* Headers ,
|
|
VARIANT_BOOL *Cancel )
|
|
{
|
|
if(!m_parent) return; // Called before init or after passivate.
|
|
|
|
#ifdef DEBUG
|
|
DebugLog( L"#################### BeforeNavigate2 %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( V_BSTR( URL ) ) );
|
|
DEBUG_CheckReadyState();
|
|
#endif
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::BeforeNavigate2 : %s", SAFEBSTR( V_BSTR( URL ) ) );
|
|
|
|
CComBSTR bstrFrame;
|
|
BSTR bstrURL = V_BSTR( URL );
|
|
|
|
|
|
if(FAILED(MPC::HTML::GetFramePath( bstrFrame, pDisp )) || !bstrFrame)
|
|
{
|
|
if(V_VT(TargetFrameName) == VT_BSTR)
|
|
{
|
|
bstrFrame = V_BSTR(TargetFrameName);
|
|
}
|
|
}
|
|
|
|
{
|
|
bool fProceed = m_parent->ProcessNavigation( m_idPanel, bstrURL, bstrFrame, m_fLoading, *Cancel );
|
|
DebugLog( L"#################### ProcessNavigation %s%s%s\n", m_fLoading ? L"loading " : L"", fProceed ? L"proceed " : L"", *Cancel ? L"cancelled " : L"" );
|
|
if(fProceed)
|
|
{
|
|
if(m_fLoading)
|
|
{
|
|
TimerControl( TIMERMODE_MORETIME );
|
|
}
|
|
else
|
|
{
|
|
TimerControl( TIMERMODE_RESTART );
|
|
|
|
NotifyStartOfNavigation( bstrURL );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void __stdcall CPCHWebBrowserEvents::NewWindow2( IDispatch* *ppDisp ,
|
|
VARIANT_BOOL *Cancel )
|
|
{
|
|
// Not disabled in Whistler.
|
|
// *Cancel = VARIANT_TRUE;
|
|
}
|
|
|
|
void __stdcall CPCHWebBrowserEvents::NavigateComplete2( IDispatch* pDisp ,
|
|
VARIANT* URL )
|
|
{
|
|
if(!m_parent) return; // Called before init or after passivate.
|
|
|
|
#ifdef DEBUG
|
|
DebugLog( L"#################### NavigateComplete2 %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( V_BSTR( URL ) ) );
|
|
DEBUG_CheckReadyState();
|
|
#endif
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::NavigateComplete2 : %s", SAFEBSTR( V_BSTR( URL ) ) );
|
|
|
|
TimerControl( TIMERMODE_MORETIME );
|
|
}
|
|
|
|
void __stdcall CPCHWebBrowserEvents::DocumentComplete( IDispatch* pDisp ,
|
|
VARIANT* URL )
|
|
{
|
|
if(!m_parent) return; // Called before init or after passivate.
|
|
|
|
BSTR bstrURL = V_BSTR( URL );
|
|
|
|
#ifdef DEBUG
|
|
DebugLog( L"#################### DocumentComplete %s %08x %s\n", m_parent->PanelName( m_idPanel ), pDisp, SAFEBSTR( bstrURL ) );
|
|
DEBUG_CheckReadyState();
|
|
#endif
|
|
|
|
DEBUG_AppendPerf( DEBUG_PERF_EVENTS_IN, L"CPCHWebBrowserEvents::DocumentComplete : %s", SAFEBSTR( bstrURL ) );
|
|
|
|
TimerControl( TIMERMODE_MORETIME );
|
|
|
|
//
|
|
// If it's one of the URL in the ignore list, don't queue the complete notification.
|
|
//
|
|
{
|
|
CPCHHelpSession* hs = m_parent->HelpSession();
|
|
|
|
if(hs && hs->IsUrlToIgnore( bstrURL, /*fRemove*/true ))
|
|
{
|
|
m_fLoading = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get to the document and extract its title.
|
|
//
|
|
{
|
|
CComPtr<IHTMLDocument2> pDoc;
|
|
|
|
if(SUCCEEDED(MPC::HTML::IDispatch_To_IHTMLDocument2( pDoc, pDisp )))
|
|
{
|
|
CComBSTR bstrTitle;
|
|
|
|
if(SUCCEEDED(pDoc->get_title( &bstrTitle )))
|
|
{
|
|
(void)m_parent->HelpSession()->RecordTitle( URL->bstrVal, bstrTitle, false );
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_fLoading)
|
|
{
|
|
if(m_pWB2)
|
|
{
|
|
tagREADYSTATE readystate;
|
|
|
|
if(SUCCEEDED(m_pWB2->get_ReadyState( &readystate )) && readystate == READYSTATE_COMPLETE)
|
|
{
|
|
bool fDone;
|
|
|
|
if(SUCCEEDED(MPC::HTML::AreAllTheFramesInTheCompleteState( fDone, m_pWB2 )) && fDone)
|
|
{
|
|
TimerControl( TIMERMODE_COMPLETE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|