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 + -
显示快捷键?