pub.cpp

来自「一个在IExplorer中运行」· C++ 代码 · 共 1,736 行 · 第 1/4 页

CPP
1,736
字号
	CComPtr<IHTMLElementCollection> spElems;
	HRESULT hr = GetElementCollection(L"IMG", pDocDisp, &spElems);
	if (SUCCEEDED(hr) && spElems)
	{
		long nCnt;
		hr = spElems->get_length(&nCnt);
		if (SUCCEEDED(hr))
		{
			for (long i = 0; i < nCnt; i++)
			{
				CComVariant varIdx;
				V_VT(&varIdx) = VT_I4;
				V_I4(&varIdx) = i;

				CComPtr<IDispatch> spItemDisp;
				hr = spElems->item(varIdx, varIdx, &spItemDisp);
				if (SUCCEEDED(hr) && spItemDisp)
				{
					CComQIPtr<IHTMLImgElement, 
						&IID_IHTMLImgElement> spImage(spItemDisp);
					if (spImage)
					{
						CComBSTR bsSrc;
						spImage->get_src(&bsSrc);
						if (SUCCEEDED(hr) && bsSrc)
						{
							if (IsAnimatedImage(bsSrc))
								HideImgElement(bsSrc, spImage);	
						}
					}
				}
			}
		}
	}
	return hr;
}

//
// A local recursive function used by BlockWebPageElements()
//
void BlockWebPageElementsRecursively(IDispatch* pDocDisp, DWORD dwElemTypes)
{
	// Remove blocked objects from view or stop their squirming

	if (dwElemTypes & ELEMTYPE_FLASH)
	{
		// flash using OBJECT tag
		BlockObject(pDocDisp, L"D27CDB6E-AE6D-11CF-96B8-444553540000");	

		// flash using EMBED tag
		BlockEmbed(pDocDisp, L".swf");	
	}

	if (dwElemTypes & ELEMTYPE_IMAGES)
	{
		BlockAnimatedImages(pDocDisp);
	}

	// Disable flash for all embedded documents.
	// By getting the container and enumerating the frames,
	// we avoid the E_ACCESSDENIED error when trying to
	// get a cross-frame document.  This method side-steps
	// IE cross-frame security.
	CComQIPtr<IOleContainer, &IID_IOleContainer> spContainer(pDocDisp);
	if (spContainer)
	{
		// Get an enumerator for the frames
		CComPtr<IEnumUnknown> spEnumerator;   
		HRESULT hr = spContainer->EnumObjects(OLECONTF_EMBEDDINGS, &spEnumerator);
		if (SUCCEEDED(hr) && spEnumerator)
		{
			// Enumerate all the frames
			CComPtr<IUnknown> spUnk;
			ULONG uFetched;   
			while (spEnumerator->Next(1, &spUnk, &uFetched) == S_OK)
			{
				// QI for IWebBrowser here to see if we have 
				// an embedded browser
				CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> spWB(spUnk);
				if (spWB)
				{
					// Yes, this is an embedded browser, get its doc
					// and disable its flash.
					CComPtr<IDispatch> spDocDisp;
					hr = spWB->get_Document(&spDocDisp);
					if (SUCCEEDED(hr) && spDocDisp)
						BlockWebPageElementsRecursively(spDocDisp, dwElemTypes);
				}
				spUnk.Release();
			}   
		}
	}
}

//
// Well OK, we don't actually disable flash movies.  We just make
// them so small we can't see them. The flash movies can be placed
// on a web page either using an OBJECT tag or an EMBED tag, so we
// have to check for both.  
//
// One annoyance is that the movies are played as the page loads, 
// and we have to wait to get the final DISPID_DOCUMENTCOMPLETE 
// or READYSTATE_COMPLETE before we can run thru the entire DOM.  
// So if you have a slow connection, movies will play until the final 
// DISPID_DOCUMENTCOMPLETE or READYSTATE_COMPLETE.  
//
// This can be somewhat mitigated by calling this function every 
// DISPID_DOWNLOADBEGIN or DISPID_DOCUMENTCOMPLETE, so that the 
// movies are hidden on a frame-by-frame basis.  A little 
// ham-fisted but fairly effective.  If someone cares to experiment 
// with that or knows a more elegant way to do it, I would like to 
// hear about it.
//
// Personnally, I just use 'Hide Flash Animations' on the context 
// menu when I come across a really bad page.  You can use it more 
// than once if you don't want to wait for the page to completely 
// load.
//

void CPub::BlockWebPageElements(DWORD dwElemTypes)
{
	if (dwElemTypes == 0)
		return;	// nothing to do

	ATLASSERT(m_spWebBrowser2);
	if (!m_spWebBrowser2)
		return;

	CComPtr<IDispatch> spDisp;
	HRESULT hr = m_spWebBrowser2->get_Document(&spDisp);
	if (SUCCEEDED(hr) && spDisp)
		BlockWebPageElementsRecursively(spDisp, dwElemTypes);
}

void CPub::NavigateToSafePage()
{
	// Navigate to about:blank.  This assures that any onunload
	// scripts are executed before the bho is shut down.
	CComBSTR bstrURL = L"about:blank";
	CComVariant vtEmpty;
	READYSTATE rs = READYSTATE_UNINITIALIZED;

	HRESULT hr = m_spWebBrowser2->Navigate(bstrURL, 
		&vtEmpty, &vtEmpty, &vtEmpty, &vtEmpty);
	ATLASSERT(SUCCEEDED(hr));

	DWORD dwCnt = GetTickCount();
	while (SUCCEEDED(hr) && rs != READYSTATE_COMPLETE)
	{
		// There may be some cases where we never get 
		// READYSTATE_COMPLETE.  Set a 10 second timeout
		// for insurance.
		if (GetTickCount() - dwCnt > 10000)
			break;

		// Don't hog the CPU.
		Sleep(100);

		// Process some messages, otherwise we never 
		// get READYSTATE_COMPLETE.
		MSG msg;
		while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
			::DispatchMessage(&msg);

		hr = m_spWebBrowser2->get_ReadyState(&rs);
		ATLASSERT(SUCCEEDED(hr));
	}
}

//
// IOleObjectWithSite Methods
//
STDMETHODIMP CPub::SetSite(IUnknown *pUnkSite)
{
	if (!pUnkSite)
	{
		ATLTRACE(_T("SetSite(): pUnkSite is NULL\n"));
	}
	else
	{
		// Query pUnkSite for the IWebBrowser2 interface.
		m_spWebBrowser2 = pUnkSite;
		if (m_spWebBrowser2)
		{
			m_spWebBrowser2->get_HWND((long*) &m_hwndIE);

			// We'll need the this pointer later when the keyboard
			// hook will be called.
			if (!AddInstance(m_hwndIE, this, GetCurrentThreadId(), GetCurrentProcessId()))
				AtlMessageBox(NULL, _T("IDS_ERR_TOOMANYWINDOWS"), IDS_PROJNAME);

			// Connect to the browser in order to handle events.
			HRESULT hr = ManageBrowserConnection(ConnType_Advise);
			if (FAILED(hr))
				ATLTRACE(_T("Failure sinking events from IWebBrowser2\n"));
		}
		else
		{
			ATLTRACE(_T("QI for IWebBrowser2 failed\n"));
		}

		// Set the keyboard hook
		m_hHook = SetWindowsHookEx(WH_KEYBOARD,
								   reinterpret_cast<HOOKPROC>(IEKeyboardProc),
								   NULL,
								   GetCurrentThreadId());
	}
	
	return S_OK;
}

//
// IDispatch Methods
//

STDMETHODIMP CPub::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
							 DISPPARAMS* pDispParams, VARIANT* pvarResult,
							 EXCEPINFO*  pExcepInfo,  UINT* puArgErr)
{
	if (!pDispParams)
		return E_INVALIDARG;
	
	switch (dispidMember)
	{
		//
		// The parameters for this DISPID are as follows:
		// [0]: Cancel flag  - VT_BYREF|VT_BOOL
		// [1]: IDispatch* - Pointer to an IDispatch interface. 
		//		You can set this parameter to the IDispatch of 
		//		a WebBrowser Control that you've created. When 
		//		you pass back an IDispatch like this, MSHTML will 
		//		use the control you've given it to open the link.
		//
		// If you cancel here, ALL popups will be blocked.
		// This will also block links that open a new window and
		// opening a link in a new window via the context menu.
		// Popup blocker gives finer control of this feature via
		// the m_bBlockNewWindow flag and hot key override.
		//
	case DISPID_NEWWINDOW2:
		ATLTRACE(_T("(%ld) DISPID_NEWWINDOW2\n"), ::GetCurrentThreadId());
		{	
			CComBSTR bsUrl;
			HRESULT hr = m_spWebBrowser2->get_LocationURL(&bsUrl);
			
			DWORD curtime;
			curtime=timeGetTime();
			
			if (m_bBlockNewWindow && 
				curtime-m_timeClick>2000 &&				
				IsEnabled())
			{
				ATLTRACE(_T("(%ld) Blocked a popup,cur-old:%ld\n"), ::GetCurrentThreadId(),curtime-m_timeClick);

				// Some links open a new window and will be blocked.
				// Give some indication to the user as to what is 
				// happening; otherwise, the link will appear to be 
				// broken.
				NotifiyUser();

				// Update statistics
				//UpdateStats(bsUrl);

				// Set the cancel flag to block the popup

				// The following two lines cause a crash on IE5.5
				//pDispParams->rgvarg[0].pvarVal->vt = VT_BOOL;
				//pDispParams->rgvarg[0].pvarVal->boolVal = VARIANT_TRUE;
				pDispParams->rgvarg[0].pboolVal[0] = VARIANT_TRUE;	// thanks to mier!
			}else{
				ATLTRACE(_T("(%ld) PopUP a popup,cur-old:%ld\n"), ::GetCurrentThreadId(),curtime-m_timeClick);
			}
			m_bBlockNewWindow = TRUE;	// Reset
			m_timeClick=0;	// Reset
		}
		break;

		//
		// The parameters for this DISPID are as follows:
		// [0]: Cancel flag  - VT_BYREF|VT_BOOL
		// [1]: HTTP headers - VT_BYREF|VT_VARIANT
		// [2]: Address of HTTP POST data  - VT_BYREF|VT_VARIANT 
		// [3]: Target frame name - VT_BYREF|VT_VARIANT 
		// [4]: Option flags - VT_BYREF|VT_VARIANT
		// [5]: URL to navigate to - VT_BYREF|VT_VARIANT
		// [6]: An object that evaluates to the top-level or frame
		//      WebBrowser object corresponding to the event. 
		// 
		// User clicked a link or launched the browser.
		//
	case DISPID_BEFORENAVIGATE2:
		ATLTRACE(_T("(%ld) DISPID_BEFORENAVIGATE2\n"), ::GetCurrentThreadId());
		m_bHotkeysEnabled = FALSE;	// Deactivate keyboard hook
		
		/*while (m_deqEventHandlers.size() > 0)
		{
			CConnInfo* pConnInfo = m_deqEventHandlers.front();
			ManageEventHandlers(pConnInfo, ConnType_Unadvise);
			delete pConnInfo;
			m_deqEventHandlers.pop_front();
		}*/

		break;
		
		//
		// The parameters for this DISPID:
		// [0]: URL navigated to - VT_BYREF|VT_VARIANT
		// [1]: An object that evaluates to the top-level or frame
		//      WebBrowser object corresponding to the event. 
		//
		// Fires after a navigation to a link is completed on either 
		// a window or frameSet element.
		//
	case DISPID_NAVIGATECOMPLETE2:
		ATLTRACE(_T("(%ld) DISPID_NAVIGATECOMPLETE2\n"), ::GetCurrentThreadId());
		m_bHotkeysEnabled = FALSE;	// Deactivate keyboard hook
		// Any new windows that might pop up after this (due to script) 
		// should be blocked....
		m_bBlockNewWindow = TRUE;	// Reset
		//m_bUserClickedLink = FALSE;	// Reset

		if (!m_pWBDisp)
		{
			// This is the IDispatch* of the top-level browser
			m_pWBDisp = pDispParams->rgvarg[1].pdispVal;
		}
		if (IsEnabled() )
		{
			DWORD dwElemTypes = 0;
			if (g_bBlockFlash)
				dwElemTypes |= ELEMTYPE_FLASH | ELEMTYPE_IMAGES;
			BlockWebPageElements(dwElemTypes);
		}
		m_bHotkeysEnabled = TRUE;
		break;
		
		//
		// The parameters for this DISPID:
		// [0]: New status bar text - VT_BSTR
		//
	case DISPID_STATUSTEXTCHANGE:
		break;
		
		//
		// The parameters for this DISPID:
		// [0]: Maximum progress - VT_I4
		// [1]: Amount of total progress - VT_I4
		//
	case DISPID_PROGRESSCHANGE:
		break;

		//
		// The parameters for this DISPID:
		// [0]: URL navigated to - VT_BYREF|VT_VARIANT
		// [1]: An object that evaluates to the top-level or frame
		//      WebBrowser object corresponding to the event. 
		//
		// Fires when a document has been completely loaded and initialized.
		// Unreliable -- currently, the DWebBrowserEvents2::DocumentComplete 
		// does not fire when the IWebBrowser2::Visible property of the 
		// WebBrowser Control is set to false (see Q259935).  Also, multiple 
		// DISPID_DOCUMENTCOMPLETE events can be fired before the final 
		// READYSTATE_COMPLETE (see Q180366).
		//
	case DISPID_DOCUMENTCOMPLETE:
		ATLTRACE(_T("(%ld) DISPID_DOCUMENTCOMPLETE\n"), ::GetCurrentThreadId());

		m_bHotkeysEnabled = FALSE;	// Deactivate keyboard hook
		//m_bUserClickedLink = FALSE;	// Reset

		{
			CConnInfo* pConnInfo = new CConnInfo(pDispParams->rgvarg[1].pdispVal);
			if (pConnInfo)
			{
				m_deqEventHandlers.push_back(pConnInfo);
				ManageEventHandlers(pConnInfo, ConnType_Advise);
			}
		}

		if (m_pWBDisp && 
			m_pWBDisp == pDispParams->rgvarg[1].pdispVal)
		{
			// If the LPDISPATCH are same, that means
			// it is the final DocumentComplete. Reset m_pWBDisp.
			ATLTRACE(_T("(%ld) DISPID_DOCUMENTCOMPLETE (final)\n"), 
				::GetCurrentThreadId());
			m_pWBDisp = NULL;

			CComPtr<IDispatch> spDisp;
			HRESULT hr = m_spWebBrowser2->get_Document(&spDisp);
			if (SUCCEEDED(hr) && spDisp)
			{
				BOOL bMustAdvise = FALSE;
				if (m_spHTMLDocument && 
					m_spHTMLDocument != spDisp)
				{
					ATLTRACE(_T("(%ld) DISPID_DOCUMENTCOMPLETE (unadvising)\n"), 
						::GetCurrentThreadId());
					
					HRESULT hr = ManagePropertyNotifyConnection(ConnType_Unadvise);
					ATLASSERT(SUCCEEDED(hr));

					m_spHTMLDocument = spDisp;
					if (m_spHTMLDocument)
					{
						hr = ManagePropertyNotifyConnection(ConnType_Advise);
						ATLASSERT(SUCCEEDED(hr));
					}
				}
				else if (!m_spHTMLDocument)
				{
					m_spHTMLDocument = spDisp;
					if (m_spHTMLDocument)
					{
						hr = ManagePropertyNotifyConnection(ConnType_Advise);
						ATLASSERT(SUCCEEDED(hr));
					}
				}

				if (m_spHTMLDocument)
				{
					// This is an HTML document (e.g., it's a 
					// Word doc or a PDF), go ahead and sink.
					hr = m_spHTMLDocument->get_parentWindow(&m_pHTMLWindow);
					ATLASSERT(SUCCEEDED(hr) && m_pHTMLWindow);
					if (FAILED(hr))
						m_pHTMLWindow = NULL;

					// Get pointers to default interfaces
					CComQIPtr<IOleObject, &IID_IOleObject> spOleObject(spDisp);
					if (spOleObject)
					{
						CComPtr<IOleClientSite> spClientSite;
						hr = spOleObject->GetClientSite(&spClientSite);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?