#include "StdAfx.h" #include "UIWebBrowser.h" #include #include #include "../Utils/downloadmgr.h" #include namespace DuiLib { //////////////////////////////////////////////////////////////////////// // IMPLEMENT_DUICONTROL(CWebBrowserUI) CWebBrowserUI::CWebBrowserUI() : m_pWebBrowser2(NULL) , _pHtmlWnd2(NULL) , m_pWebBrowserEventHandler(NULL) , m_bAutoNavi(false) , m_dwRef(0) , m_dwCookie(0) { m_clsid=CLSID_WebBrowser; m_sHomePage.Empty(); } bool CWebBrowserUI::DoCreateControl() { if (!CActiveXUI::DoCreateControl()) return false; GetManager()->AddTranslateAccelerator(this); GetControl(IID_IWebBrowser2,(LPVOID*)&m_pWebBrowser2); if ( m_bAutoNavi && !m_sHomePage.IsEmpty()) { this->Navigate2(m_sHomePage); } RegisterEventHandler(TRUE); return true; } void CWebBrowserUI::ReleaseControl() { m_bCreated=false; GetManager()->RemoveTranslateAccelerator(this); RegisterEventHandler(FALSE); } CWebBrowserUI::~CWebBrowserUI() { ReleaseControl(); } STDMETHODIMP CWebBrowserUI::GetTypeInfoCount( UINT *iTInfo ) { *iTInfo = 0; return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::GetTypeInfo( UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo ) { return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::GetIDsOfNames( REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid,DISPID *rgDispId ) { return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::Invoke( DISPID dispIdMember, REFIID riid, LCID lcid,WORD wFlags, DISPPARAMS* pDispParams,VARIANT* pVarResult, EXCEPINFO* pExcepInfo,UINT* puArgErr ) { if ((riid != IID_NULL)) return E_INVALIDARG; switch(dispIdMember) { case DISPID_BEFORENAVIGATE2: BeforeNavigate2( pDispParams->rgvarg[6].pdispVal, pDispParams->rgvarg[5].pvarVal, pDispParams->rgvarg[4].pvarVal, pDispParams->rgvarg[3].pvarVal, pDispParams->rgvarg[2].pvarVal, pDispParams->rgvarg[1].pvarVal, pDispParams->rgvarg[0].pboolVal); break; case DISPID_COMMANDSTATECHANGE: CommandStateChange( pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].boolVal); break; case DISPID_NAVIGATECOMPLETE2: NavigateComplete2( pDispParams->rgvarg[1].pdispVal, pDispParams->rgvarg[0].pvarVal); break; case DISPID_NAVIGATEERROR: NavigateError( pDispParams->rgvarg[4].pdispVal, pDispParams->rgvarg[3].pvarVal, pDispParams->rgvarg[2].pvarVal, pDispParams->rgvarg[1].pvarVal, pDispParams->rgvarg[0].pboolVal); break; case DISPID_STATUSTEXTCHANGE: break; // case DISPID_NEWWINDOW2: // break; case DISPID_NEWWINDOW3: NewWindow3( pDispParams->rgvarg[4].ppdispVal, pDispParams->rgvarg[3].pboolVal, pDispParams->rgvarg[2].uintVal, pDispParams->rgvarg[1].bstrVal, pDispParams->rgvarg[0].bstrVal); break; case DISPID_TITLECHANGE: { TitleChange(pDispParams->rgvarg[0].bstrVal); break; } case DISPID_DOCUMENTCOMPLETE: { DocumentComplete( pDispParams->rgvarg[1].pdispVal, pDispParams->rgvarg[0].pvarVal); break; } default: return DISP_E_MEMBERNOTFOUND; } return S_OK; } STDMETHODIMP CWebBrowserUI::QueryInterface( REFIID riid, LPVOID *ppvObject ) { *ppvObject = NULL; if( riid == IID_IDocHostUIHandler) *ppvObject = static_cast(this); else if( riid == IID_IDispatch) *ppvObject = static_cast(this); else if( riid == IID_IServiceProvider) *ppvObject = static_cast(this); else if(riid == IID_IInternetSecurityManager ) { *ppvObject = static_cast(this); } else if (riid == IID_IOleCommandTarget) *ppvObject = static_cast(this); if( *ppvObject != NULL ) AddRef(); return *ppvObject == NULL ? E_NOINTERFACE : S_OK; } STDMETHODIMP_(ULONG) CWebBrowserUI::AddRef() { InterlockedIncrement(&m_dwRef); return m_dwRef; } STDMETHODIMP_(ULONG) CWebBrowserUI::Release() { ULONG ulRefCount = InterlockedDecrement(&m_dwRef); return ulRefCount; } void CWebBrowserUI::Navigate2( LPCTSTR lpszUrl ) { if (lpszUrl == NULL) return; if (m_pWebBrowser2) { CDuiVariant url; url.vt=VT_BSTR; url.bstrVal=T2BSTR(lpszUrl); HRESULT hr = m_pWebBrowser2->Navigate2(&url, NULL, NULL, NULL, NULL); } } void CWebBrowserUI::Refresh() { if (m_pWebBrowser2) { m_pWebBrowser2->Refresh(); } } void CWebBrowserUI::GoBack() { if (m_pWebBrowser2) { m_pWebBrowser2->GoBack(); } } void CWebBrowserUI::GoForward() { if (m_pWebBrowser2) { m_pWebBrowser2->GoForward(); } } /// DWebBrowserEvents2 void CWebBrowserUI::BeforeNavigate2( IDispatch *pDisp,VARIANT *&url,VARIANT *&Flags,VARIANT *&TargetFrameName,VARIANT *&PostData,VARIANT *&Headers,VARIANT_BOOL *&Cancel ) { if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->BeforeNavigate2(this, pDisp,url,Flags,TargetFrameName,PostData,Headers,Cancel); } } void CWebBrowserUI::NavigateError( IDispatch *pDisp,VARIANT * &url,VARIANT *&TargetFrameName,VARIANT *&StatusCode,VARIANT_BOOL *&Cancel ) { if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->NavigateError(this, pDisp,url,TargetFrameName,StatusCode,Cancel); } } void CWebBrowserUI::NavigateComplete2( IDispatch *pDisp,VARIANT *&url ) { CComPtr spDoc; m_pWebBrowser2->get_Document(&spDoc); if (spDoc) { CComQIPtr spCustomDoc(spDoc); if (spCustomDoc) spCustomDoc->SetUIHandler(this); } if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->NavigateComplete2(this, pDisp,url); } } void CWebBrowserUI::ProgressChange( LONG nProgress, LONG nProgressMax ) { if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->ProgressChange(this, nProgress,nProgressMax); } } void CWebBrowserUI::NewWindow3( IDispatch **pDisp, VARIANT_BOOL *&Cancel, DWORD dwFlags, BSTR bstrUrlContext, BSTR bstrUrl ) { if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->NewWindow3(this, pDisp,Cancel,dwFlags,bstrUrlContext,bstrUrl); } } void CWebBrowserUI::CommandStateChange(long Command,VARIANT_BOOL Enable) { if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->CommandStateChange(this, Command,Enable); } } void CWebBrowserUI::TitleChange(BSTR bstrTitle) { if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->TitleChange(this, bstrTitle); } } void CWebBrowserUI::DocumentComplete(IDispatch *pDisp, VARIANT *&url) { if (m_pWebBrowserEventHandler) { m_pWebBrowserEventHandler->DocumentComplete(this, pDisp, url); } } // IDownloadManager STDMETHODIMP CWebBrowserUI::Download( /* [in] */ IMoniker *pmk, /* [in] */ IBindCtx *pbc, /* [in] */ DWORD dwBindVerb, /* [in] */ LONG grfBINDF, /* [in] */ BINDINFO *pBindInfo, /* [in] */ LPCOLESTR pszHeaders, /* [in] */ LPCOLESTR pszRedir, /* [in] */ UINT uiCP ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->Download(this, pmk,pbc,dwBindVerb,grfBINDF,pBindInfo,pszHeaders,pszRedir,uiCP); } return S_OK; } // IDocHostUIHandler STDMETHODIMP CWebBrowserUI::ShowContextMenu( DWORD dwID, POINT* pptPosition, IUnknown* pCommandTarget, IDispatch* pDispatchObjectHit ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->ShowContextMenu(this, dwID,pptPosition,pCommandTarget,pDispatchObjectHit); } return S_FALSE; } STDMETHODIMP CWebBrowserUI::GetHostInfo( DOCHOSTUIINFO* pInfo ) { if (pInfo != NULL) { pInfo->dwFlags |= DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_NO3DOUTERBORDER; } if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->GetHostInfo(this, pInfo); } return S_OK; } STDMETHODIMP CWebBrowserUI::ShowUI( DWORD dwID, IOleInPlaceActiveObject* pActiveObject, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* pFrame, IOleInPlaceUIWindow* pDoc ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->ShowUI(this, dwID,pActiveObject,pCommandTarget,pFrame,pDoc); } return S_OK; } STDMETHODIMP CWebBrowserUI::HideUI() { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->HideUI(this); } return S_OK; } STDMETHODIMP CWebBrowserUI::UpdateUI() { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->UpdateUI(this); } return S_OK; } STDMETHODIMP CWebBrowserUI::EnableModeless( BOOL fEnable ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->EnableModeless(this, fEnable); } return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::OnDocWindowActivate( BOOL fActivate ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->OnDocWindowActivate(this, fActivate); } return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::OnFrameWindowActivate( BOOL fActivate ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->OnFrameWindowActivate(this, fActivate); } return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::ResizeBorder( LPCRECT prcBorder, IOleInPlaceUIWindow* pUIWindow, BOOL fFrameWindow ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->ResizeBorder(this, prcBorder,pUIWindow,fFrameWindow); } return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::TranslateAccelerator( LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->TranslateAccelerator(this, lpMsg,pguidCmdGroup,nCmdID); } return S_FALSE; } LRESULT CWebBrowserUI::TranslateAccelerator( MSG *pMsg ) { if(pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) return S_FALSE; if( m_pWebBrowser2 == NULL ) return E_NOTIMPL; // 当前Web窗口不是焦点,不处理加速键 BOOL bIsChild = FALSE; HWND hTempWnd = NULL; HWND hWndFocus = ::GetFocus(); hTempWnd = hWndFocus; while(hTempWnd != NULL) { if(hTempWnd == m_hwndHost) { bIsChild = TRUE; break; } hTempWnd = ::GetParent(hTempWnd); } if(!bIsChild) return S_FALSE; IOleInPlaceActiveObject *pObj; if (FAILED(m_pWebBrowser2->QueryInterface(IID_IOleInPlaceActiveObject, (LPVOID *)&pObj))) return S_FALSE; HRESULT hResult = pObj->TranslateAccelerator(pMsg); pObj->Release(); return hResult; } STDMETHODIMP CWebBrowserUI::GetOptionKeyPath( LPOLESTR* pchKey, DWORD dwReserved ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->GetOptionKeyPath(this, pchKey,dwReserved); } return E_NOTIMPL; } STDMETHODIMP CWebBrowserUI::GetDropTarget( IDropTarget* pDropTarget, IDropTarget** ppDropTarget ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->GetDropTarget(this, pDropTarget,ppDropTarget); } return S_FALSE; // 使用系统拖拽 } STDMETHODIMP CWebBrowserUI::GetExternal( IDispatch** ppDispatch ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->GetExternal(this, ppDispatch); } return S_FALSE; } STDMETHODIMP CWebBrowserUI::TranslateUrl( DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->TranslateUrl(this, dwTranslate,pchURLIn,ppchURLOut); } else { *ppchURLOut = 0; return E_NOTIMPL; } } STDMETHODIMP CWebBrowserUI::FilterDataObject( IDataObject* pDO, IDataObject** ppDORet ) { if (m_pWebBrowserEventHandler) { return m_pWebBrowserEventHandler->FilterDataObject(this, pDO,ppDORet); } else { *ppDORet = 0; return E_NOTIMPL; } } void CWebBrowserUI::SetWebBrowserEventHandler( CWebBrowserEventHandler* pEventHandler ) { if ( pEventHandler!=NULL && m_pWebBrowserEventHandler!=pEventHandler) m_pWebBrowserEventHandler=pEventHandler; } void CWebBrowserUI::Refresh2( int Level ) { CDuiVariant vLevel; vLevel.vt=VT_I4; vLevel.intVal=Level; m_pWebBrowser2->Refresh2(&vLevel); } void CWebBrowserUI::SetAttribute( LPCTSTR pstrName, LPCTSTR pstrValue ) { if (_tcsicmp(pstrName, _T("homepage")) == 0) { m_sHomePage = pstrValue; } else if (_tcsicmp(pstrName, _T("autonavi"))==0) { m_bAutoNavi = (_tcsicmp(pstrValue, _T("true")) == 0); } else CActiveXUI::SetAttribute(pstrName, pstrValue); } void CWebBrowserUI::NavigateHomePage() { if (!m_sHomePage.IsEmpty()) this->NavigateUrl(m_sHomePage); } void CWebBrowserUI::NavigateUrl( LPCTSTR lpszUrl ) { if (m_pWebBrowser2 && lpszUrl) { m_pWebBrowser2->Navigate((BSTR)SysAllocString(T2BSTR(lpszUrl)),NULL,NULL,NULL,NULL); } } LPCTSTR CWebBrowserUI::GetClass() const { return _T("WebBrowserUI"); } LPVOID CWebBrowserUI::GetInterface( LPCTSTR pstrName ) { if( _tcsicmp(pstrName, DUI_CTR_WEBBROWSER) == 0 ) return static_cast(this); return CActiveXUI::GetInterface(pstrName); } void CWebBrowserUI::SetHomePage( LPCTSTR lpszUrl ) { m_sHomePage.Format(_T("%s"),lpszUrl); } LPCTSTR CWebBrowserUI::GetHomePage() { return m_sHomePage; } void CWebBrowserUI::SetAutoNavigation( bool bAuto /*= TRUE*/ ) { if (m_bAutoNavi==bAuto) return; m_bAutoNavi=bAuto; } bool CWebBrowserUI::IsAutoNavigation() { return m_bAutoNavi; } STDMETHODIMP CWebBrowserUI::QueryService( REFGUID guidService, REFIID riid, void** ppvObject ) { HRESULT hr = E_NOINTERFACE; *ppvObject = NULL; if ( guidService == SID_SDownloadManager && riid == IID_IDownloadManager) { *ppvObject = this; return S_OK; } if(guidService == SID_SInternetSecurityManager && riid == IID_IInternetSecurityManager) { *ppvObject = this; return S_OK; } return hr; } HRESULT CWebBrowserUI::RegisterEventHandler( BOOL inAdvise ) { CComPtr pWebBrowser; CComPtr pCPC; CComPtr pCP; HRESULT hr = GetControl(IID_IWebBrowser2, (void**)&pWebBrowser); if (FAILED(hr)) return hr; hr=pWebBrowser->QueryInterface(IID_IConnectionPointContainer,(void **)&pCPC); if (FAILED(hr)) return hr; hr=pCPC->FindConnectionPoint(DIID_DWebBrowserEvents2,&pCP); if (FAILED(hr)) return hr; if (inAdvise) { hr = pCP->Advise((IDispatch*)this, &m_dwCookie); } else { hr = pCP->Unadvise(m_dwCookie); } return hr; } DISPID CWebBrowserUI::FindId( IDispatch *pObj, LPOLESTR pName ) { DISPID id = 0; if(FAILED(pObj->GetIDsOfNames(IID_NULL,&pName,1,LOCALE_SYSTEM_DEFAULT,&id))) id = -1; return id; } HRESULT CWebBrowserUI::InvokeMethod( IDispatch *pObj, LPOLESTR pMehtod, VARIANT *pVarResult, VARIANT *ps, int cArgs ) { DISPID dispid = FindId(pObj, pMehtod); if(dispid == -1) return E_FAIL; DISPPARAMS dispparams; dispparams.cArgs = cArgs; dispparams.rgvarg = ps; dispparams.cNamedArgs = 0; dispparams.rgdispidNamedArgs = NULL; return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, pVarResult, NULL, NULL); } HRESULT CWebBrowserUI::GetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue ) { DISPID dispid = FindId(pObj, pName); if(dispid == -1) return E_FAIL; DISPPARAMS ps; ps.cArgs = 0; ps.rgvarg = NULL; ps.cNamedArgs = 0; ps.rgdispidNamedArgs = NULL; return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &ps, pValue, NULL, NULL); } HRESULT CWebBrowserUI::SetProperty( IDispatch *pObj, LPOLESTR pName, VARIANT *pValue ) { DISPID dispid = FindId(pObj, pName); if(dispid == -1) return E_FAIL; DISPPARAMS ps; ps.cArgs = 1; ps.rgvarg = pValue; ps.cNamedArgs = 0; ps.rgdispidNamedArgs = NULL; return pObj->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYPUT, &ps, NULL, NULL, NULL); } IDispatch* CWebBrowserUI::GetHtmlWindow() { IDispatch* pDp = NULL; HRESULT hr; if (m_pWebBrowser2) hr=m_pWebBrowser2->get_Document(&pDp); if (FAILED(hr)) return NULL; CComQIPtr pHtmlDoc2 = pDp; if (pHtmlDoc2 == NULL) return NULL; hr=pHtmlDoc2->get_parentWindow(&_pHtmlWnd2); if (FAILED(hr)) return NULL; IDispatch *pHtmlWindown = NULL; hr=_pHtmlWnd2->QueryInterface(IID_IDispatch, (void**)&pHtmlWindown); if (FAILED(hr)) return NULL; return pHtmlWindown; } IWebBrowser2* CWebBrowserUI::GetWebBrowser2( void ) { return m_pWebBrowser2; } HRESULT STDMETHODCALLTYPE CWebBrowserUI::QueryStatus( __RPC__in_opt const GUID *pguidCmdGroup, ULONG cCmds, __RPC__inout_ecount_full(cCmds ) OLECMD prgCmds[ ], __RPC__inout_opt OLECMDTEXT *pCmdText ) { HRESULT hr = OLECMDERR_E_NOTSUPPORTED; return hr; } HRESULT STDMETHODCALLTYPE CWebBrowserUI::Exec( __RPC__in_opt const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, __RPC__in_opt VARIANT *pvaIn, __RPC__inout_opt VARIANT *pvaOut ) { HRESULT hr = S_OK; if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler)) { switch (nCmdID) { case OLECMDID_SHOWSCRIPTERROR: { IHTMLDocument2* pDoc = NULL; IHTMLWindow2* pWindow = NULL; IHTMLEventObj* pEventObj = NULL; BSTR rgwszNames[5] = { SysAllocString(L"errorLine"), SysAllocString(L"errorCharacter"), SysAllocString(L"errorCode"), SysAllocString(L"errorMessage"), SysAllocString(L"errorUrl") }; DISPID rgDispIDs[5]; VARIANT rgvaEventInfo[5]; DISPPARAMS params; BOOL fContinueRunningScripts = true; int i; params.cArgs = 0; params.cNamedArgs = 0; // Get the document that is currently being viewed. hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc); // Get document.parentWindow. hr = pDoc->get_parentWindow(&pWindow); pDoc->Release(); // Get the window.event object. hr = pWindow->get_event(&pEventObj); // Get the error info from the window.event object. for (i = 0; i < 5; i++) { // Get the property's dispID. hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1, LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]); // Get the value of the property. hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, ¶ms, &rgvaEventInfo[i], NULL, NULL); SysFreeString(rgwszNames[i]); } // At this point, you would normally alert the user with // the information about the error, which is now contained // in rgvaEventInfo[]. Or, you could just exit silently. (*pvaOut).vt = VT_BOOL; if (fContinueRunningScripts) { // Continue running scripts on the page. (*pvaOut).boolVal = VARIANT_TRUE; } else { // Stop running scripts on the page. (*pvaOut).boolVal = VARIANT_FALSE; } break; } default: hr = OLECMDERR_E_NOTSUPPORTED; break; } } else { hr = OLECMDERR_E_UNKNOWNGROUP; } return (hr); } }