pub.cpp

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

CPP
1,736
字号
						if (SUCCEEDED(hr) && spClientSite)
						{
							m_spDefaultDocHostUIHandler = spClientSite;
							m_spDefaultOleCommandTarget = spClientSite;
						}
					}

					// Set this class to be the IDocHostUIHandler
					CComQIPtr<ICustomDoc, &IID_ICustomDoc> spCustomDoc(spDisp);
					if (spCustomDoc)
					{
						hr = spCustomDoc->SetUIHandler(this);
						ATLASSERT(SUCCEEDED(hr));
					}

					// Create a CPubDomExtender object that will be used by
					// window.external
					CComObject<CPubDomExtender>* pDomExt;
					hr = CComObject<CPubDomExtender>::CreateInstance (&pDomExt);
					ATLASSERT(SUCCEEDED(hr));
					if (SUCCEEDED(hr))
					{
						CComQIPtr<IDispatch> spDisp = pDomExt;
						m_spExtDispatch = spDisp;
						pDomExt->m_pPub = this;
					}

					// Check for flash here because READYSTATE_COMPLETE
					// seems to be unreliable.
					if (IsEnabled() )
					{
						DWORD dwElemTypes = 0;
						if (g_bBlockFlash)
							dwElemTypes |= ELEMTYPE_FLASH | ELEMTYPE_IMAGES;
						BlockWebPageElements(dwElemTypes);
					}
				}
			} 
		}
		m_bHotkeysEnabled = TRUE;
		break;
		
		//
		// No parameters
		//
		// Fires when a navigation operation is beginning.
		//
	case DISPID_DOWNLOADBEGIN:
		ATLTRACE(_T("(%ld) DISPID_DOWNLOADBEGIN\n"), ::GetCurrentThreadId());
		
		break;
		
		//
		// No parameters
		//
		// Fires when a navigation operation finishes, is halted, or fails.
		//
	case DISPID_DOWNLOADCOMPLETE:
		ATLTRACE(_T("(%ld) DISPID_DOWNLOADCOMPLETE\n"), ::GetCurrentThreadId());
		{
			if (IsEnabled() )
			{
				DWORD dwElemTypes = 0;
				if (g_bBlockFlash)
					dwElemTypes |= ELEMTYPE_FLASH | ELEMTYPE_IMAGES;
				BlockWebPageElements(dwElemTypes);
			}
		}
		break;
		
		//
		// The parameters for this DISPID:
		// [0]: Enabled state - VT_BOOL
		// [1]: Command identifier - VT_I4
		//
	case DISPID_COMMANDSTATECHANGE:
		break;
		
		//
		// The parameters for this DISPID:
		// [0]: Document title - VT_BSTR
		// [1]: An object that evaluates to the top-level or frame
		//      WebBrowser object corresponding to the event.
		//
	case DISPID_TITLECHANGE:
		break;
		
		//
		// The parameters for this DISPID:
		// [0]: Name of property that changed - VT_BSTR
		//
	case DISPID_PROPERTYCHANGE:
		break;

		//
		// No parameters
		//
		// The BHO docs in MSDN say to use DISPID_QUIT, but this is an error.
		// The BHO never gets a DISPID_QUIT and thus the browser connection
		// never gets unadvised and so the BHO never gets the FinalRelease().
		// This is bad.  So use DISPID_ONQUIT instead and everything is cool --
		// EXCEPT when you exit the browser when viewing a page that launches
		// a popup in the onunload event!  In that case the BHO is already
		// unadvised so it does not intercept the popup.  So the trick is to
		// navigate to a known page (I used the about:blank page) that does 
		// not have a popup in the onunload event before unadvising.
		//
	case DISPID_ONQUIT:
		ATLTRACE(_T("(%ld) DISPID_QUIT\n"), ::GetCurrentThreadId());
		{
			NavigateToSafePage();

			// OK, we are now on a 'safe' page with no popups.
			// Set the shutting down flag to stop all normal
			// processing, like checking the whitelist, while 
			// the bho is shut down.
			m_bShuttingDown = TRUE;

			// Unadvise
			HRESULT hr = ManagePropertyNotifyConnection(ConnType_Unadvise);
			ATLASSERT(SUCCEEDED(hr));

			while (m_deqEventHandlers.size() > 0)
			{
				CConnInfo* pConnInfo = m_deqEventHandlers.front();
				ManageEventHandlers(pConnInfo, ConnType_Unadvise);
				delete pConnInfo;
				m_deqEventHandlers.pop_front();
			}

			hr = ManageBrowserConnection(ConnType_Unadvise);
			ATLASSERT(SUCCEEDED(hr));

			// Release the document
			if (m_spHTMLDocument)
				m_spHTMLDocument.Release();

			if (RemoveInstance(this, m_hwndIE, GetCurrentProcessId()) && m_hHook)
				UnhookWindowsHookEx(m_hHook);

			// FinalRelease should get called next.
			// If not, you have not released everything.
		}
		break;

	default:
		break;
   }
   
   return S_OK;
}

//
// IDocHostUIHandler Methods
//

//
// Window procedure for handling enabling/disabling/checking in our context menu.
//
LRESULT CALLBACK CtxMenuWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	if (uMsg == WM_INITMENUPOPUP)
	{
		if (wParam == (WPARAM) g_hPubMenu)
		{
			// This is our menu
			::CheckMenuItem(g_hPubMenu, ID_CTXMENU_ENABLEPOPUPBLOCKER, 
				MF_BYCOMMAND | (g_bEnabled ? MF_CHECKED : MF_UNCHECKED));
			::CheckMenuItem(g_hPubMenu, ID_CTXMENU_DELETEFLASHANIMATIONS, 
				MF_BYCOMMAND | (g_bBlockFlash ? MF_CHECKED : MF_UNCHECKED));
			return 0;
		}
	}
	return CallWindowProc(g_lpPrevWndProc, hwnd, uMsg, wParam, lParam);
}

// 
// Insert our Popup Blocker sub menu into the context menu
//
HRESULT CPub::ShowContextMenu(DWORD dwID,
                              POINT *ppt,
                              IUnknown *pcmdTarget,
                              IDispatch *pdispObject) 
{
	// Return S_OK to tell MSHTML not to display its own menu
	// Return S_FALSE displays default MSHTML menu

	
    #define IDR_BROWSE_CONTEXT_MENU  24641
    #define SHDVID_GETMIMECSETMENU   27
    #define SHDVID_ADDMENUEXTENSIONS 53

    HRESULT hr;

    CComPtr<IOleCommandTarget> spCT;
    hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
	if (FAILED(hr))
		return S_FALSE;

    CComPtr<IOleWindow> spWnd;
    hr = pcmdTarget->QueryInterface(IID_IOleWindow, (void**)&spWnd);
	if (FAILED(hr))
		return S_FALSE;

    HWND hwnd;
    hr = spWnd->GetWindow(&hwnd);
	if (FAILED(hr))
		return S_FALSE;

	hr = S_FALSE;

    HINSTANCE hinstSHDOCLC = LoadLibrary(_T("SHDOCLC.DLL"));
	if (hinstSHDOCLC)
	{
		HMENU hCtxMenu = LoadMenu(hinstSHDOCLC, MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
		if (hCtxMenu)
		{
			HMENU hSubMenu = GetSubMenu(hCtxMenu, dwID);
			if (hSubMenu)
			{
				// Get the language submenu
				CComVariant var;
				hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
				if (SUCCEEDED(hr))
				{
					MENUITEMINFO mii = {0};
					mii.cbSize = sizeof(mii);
					mii.fMask  = MIIM_SUBMENU;
					mii.hSubMenu = (HMENU) var.byref;

					// Add language submenu to Encoding context item
					SetMenuItemInfo(hSubMenu, IDM_LANGUAGE, FALSE, &mii);

					// Insert Shortcut Menu Extensions from registry
					CComVariant var1;
					V_VT(&var1) = VT_INT_PTR;
					V_BYREF(&var1) = hSubMenu;

					CComVariant var2;
					V_VT(&var2) = VT_I4;
					V_I4(&var2) = dwID;

					// This fails under Win98, but is OK under Win98SE
					hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
					if (SUCCEEDED(hr))
					{
						// Insert our menu at the top of the context menu
						HMENU hMenu = NULL;
						HINSTANCE hInst = (*_pModule).GetResourceInstance();
						if (hInst)
						{
							hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_PUBMENU));
							if (hMenu)
							{
								CString s;
								s.LoadString(IDS_MENU_TEXT);

								g_hPubMenu = ::GetSubMenu(hMenu, 0);
								::InsertMenu(hSubMenu, 0, MF_POPUP | MF_BYPOSITION, (UINT_PTR) g_hPubMenu, s);
								::InsertMenu(hSubMenu, 1, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);
							}
						}

						// Subclass IE window.
						// This is required in order to enable our menu.  Otherwise, IE 
						// disregards menu items it doesn't recognize.
#pragma warning( push )
#pragma warning( disable : 4311 )
#pragma warning( disable : 4312 )
						g_lpPrevWndProc = (WNDPROC)::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)CtxMenuWndProc);
#pragma warning( pop ) 

						// Show shortcut menu
						int nCmd = ::TrackPopupMenu(hSubMenu,
                            TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
							ppt->x,
							ppt->y,
							0,
							hwnd,
							(RECT*)NULL);

						// Unsubclass IE window
#pragma warning( push )
#pragma warning( disable : 4311 )
						::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)g_lpPrevWndProc);
						g_lpPrevWndProc = NULL;
#pragma warning( pop ) 

						if (hMenu)
						{
							DestroyMenu(hMenu);
							g_hPubMenu = NULL;
						}

						if (nCmd == ID_CTXMENU_ENABLEPOPUPBLOCKER)
						{
							EnablePopupBlocker();
						}
						else if (nCmd == ID_CTXMENU_DELETEFLASHANIMATIONS)
						{
							g_bBlockFlash = !g_bBlockFlash;
							DWORD dwElemTypes = 0;
							if (g_bBlockFlash)
							{
								try
								{
									CRegKey rk;
									DWORD dwErr = rk.Open(HKEY_CURRENT_USER, g_sCoRegKey + g_sPubRegKey);
									if (dwErr == ERROR_SUCCESS)
										rk.SetDWORDValue(_T("BlockFlash"), g_bBlockFlash);
								}
								catch(...)
								{
								}
								dwElemTypes |= ELEMTYPE_FLASH | ELEMTYPE_IMAGES;
								BlockWebPageElements(dwElemTypes);							
							}
						}
						//else if (nCmd == ID_CTXMENU_OPTIONS)
						//{
						//	EditOptions(0);
						//}
						//else if (nCmd == ID_CTXMENU_WHITELIST)
						//{
						//	EditOptions(3);
						//}
						//else if (nCmd == ID_CTXMENU_HISTORY)
						//{
						//	EditOptions(4);
						//}
						//else if (nCmd == ID_CTXMENU_ABOUT)
						//{
						//	EditOptions(5);
						//}
						else
						{
						//	ATLTRACE(_T("ContextMenu cmd = %d\n"), nCmd);

							if (nCmd == IDM_FOLLOWLINKN)
							{
								// Allow user to open link in new window
								m_bBlockNewWindow = FALSE;
							}

							// Send selected shortcut menu item command to shell
							LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, nCmd, NULL);
						}
					}
				}
			}

			DestroyMenu(hCtxMenu);
		}

		FreeLibrary(hinstSHDOCLC);
	}
	return (SUCCEEDED(hr) ? hr : S_FALSE);
}

//
// IPropertyNotifySink methods
//
STDMETHODIMP CPub::OnChanged(DISPID dispID)
{
	if (DISPID_READYSTATE == dispID)
	{
		// check the value of the readystate property
		if (m_spHTMLDocument)
		{
			VARIANT vResult = {0};
			EXCEPINFO excepInfo;
			UINT uArgErr;
			DISPPARAMS dp = {NULL, NULL, 0, 0};

			HRESULT hr = m_spHTMLDocument->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
				DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo, &uArgErr);

			if (SUCCEEDED(hr))
			{
				ATLASSERT(VT_I4 == V_VT(&vResult));
				READYSTATE m_lReadyState = (READYSTATE)V_I4(&vResult);

				switch (m_lReadyState)
				{	
				case READYSTATE_UNINITIALIZED:
					ATLTRACE(_T("OnChanged: readyState = Uninitialized\n"));
					break;
				case READYSTATE_LOADING:
					ATLTRACE(_T("OnChanged: readyState = Loading\n"));
					break;	
				case READYSTATE_LOADED:
					ATLTRACE(_T("OnChanged: readyState = Loaded\n"));
					break;
				case READYSTATE_INTERACTIVE:
					ATLTRACE(_T("OnChanged: readyState = Interactive\n"));
					break;
				case READYSTATE_COMPLETE:
					ATLTRACE(_T("OnChanged: readyState = Complete\n"));

					// Check for flash here because DISPID_DOCUMENTCOMPLETE
					// seems to be unreliable.
					if (IsEnabled() )
					{
						DWORD dwElemTypes = 0;
						if (g_bBlockFlash)
							dwElemTypes |= ELEMTYPE_FLASH | ELEMTYPE_IMAGES;
						BlockWebPageElements(dwElemTypes);
					}
					break;
				}
				VariantClear(&vResult);
			}
			else
			{
				ATLTRACE(_T("OnChanged: Unable to obtain readyState value\n"));
			}
		}
	}
	else
	{
		ATLTRACE(_T("OnChanged: %ld\n"), dispID);
	}

	return S_OK;
}

//
// Return TRUE if the popup blocker is enabled.
//
BOOL CPub::IsEnabled()
{
	return (!m_bShuttingDown && g_bEnabled );
}

⌨️ 快捷键说明

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