Click here to Skip to main content
Email Password   helpLost your password?

Sample Image - PopupBlocker.jpg

Introduction

Why pay money for a popup window blocker when it's so easy to roll your own?  Popup Blocker is implemented in ATL as a browser helper object (BHO).  A BHO is a DLL that will attach itself to every new instance of Internet Explorer.  In the BHO you can intercept Internet Explorer events, and access the browser window and document object model (DOM).  This gives you a great deal of flexibility in modifying Internet Explorer behavior.

There are several advantages to using a BHO over an application that continually scans open windows for keywords in the title.  The BHO is event driven and does not run in a loop or use a timer, so it doesn't use any CPU cycles if nothing is happening.  The BHO will prevent popups from opening and downloading their content, so you save bandwidth.  The BHO can be written so as to eliminate the need for a keyword list or blacklist.

Also included, but not discussed in this article, is a Windows Installer setup program.

Creating the BHO

A minimal BHO is a COM server DLL that implements IObjectWithSite.  Create a new ATL Project and accept the default settings (attributed, DLL).  Add an ATL Simple Object, give it a name and on the Options tab select Aggregation: No and Support: IObjectWithSite

The only method on IObjectWithSite that must be implemented is SetSite().  IE will call SetSite with a pointer to IUnknown which we can query for a pointer to IWebBrowser2, which gives us the keys to the house.

//

// 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)
        {
            // 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"));
        }
    }
    
    return S_OK;
}
        

Once we have the pointer to IWebBrowser2 we can hook up to the DWebBrowserEvents2 connection point in order to receive the NewWindow2 event.  This event is sent every time a new window is about to open and allows you to cancel the operation -- exactly what we want for a popup window blocker.  

//

// Funnel web browser events through this class

//

HRESULT CPub::ManageBrowserConnection(ConnectType eConnectType)
{
    if (eConnectType == ConnType_Unadvise && m_dwBrowserCookie == 0)
        return S_OK;    // not advised, nothing to do


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

    CComQIPtr spCPC(m_spWebBrowser2);
    
    HRESULT hr = E_FAIL;
    if (spCPC)
    {
        CComPtr spCP;
        hr = spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);
        if (SUCCEEDED(hr))
        {
            if (eConnectType == ConnType_Advise)
            {
                ATLASSERT(m_dwBrowserCookie == 0);
                hr = spCP->Advise((IDispatch*)this, &m_dwBrowserCookie);
            }
            else 
            {
                hr = spCP->Unadvise(m_dwBrowserCookie);
                m_dwBrowserCookie = 0;
            }
        }
    }
    return hr;
}

To create the event handler we have to derive our class from IDispatchImpl.

class ATL_NO_VTABLE CPub : 
    public IObjectWithSiteImpl<CPUB>,
    public IDispatchImpl
        

Then add the Invoke method as follows:

//

// 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. 

        //

        // If you cancel here, ALL popups will be blocked.

        //

    case DISPID_NEWWINDOW2:
        // Set the cancel flag to block popups

        pDispParams->rgvarg[0].pvarVal->vt = VT_BOOL;
        pDispParams->rgvarg[0].pvarVal->boolVal = VARIANT_TRUE;
        break;
    default:
        break;
   }
   
   return S_OK;
}

Once you get this much to compile, to make IE load the BHO you need to add the CLSID to the registry.

HKLM {
    SOFTWARE {
        Microsoft {    
            Windows {
                CurrentVersion {
                    Explorer {
                        'Browser Helper Objects'
                        {
                            {C68AE9C0-0909-4DDC-B661-C1AFB9F5AE53}
                        }
                    }
                }
            }
        }
}
        

If you've done everything right up to now, the BHO will load with every instance of IE and prevent all popup windows from opening. You can quickly test this by launching IE and selecting Open in New Window from the context menu. If the BHO is working properly the command should fail. 

One problem you may notice is that even with no open browser windows the linker will sometimes fail because some process is using the BHO, forcing you to reboot the computer to release it.  Needless to say, this can quickly become annoying.  What is happening is that Windows Explorer also uses IE for its GUI, and so also loads the BHO.  Since we want our BHO to load only when we launch IE, we need to make a change to DllMain so that it doesn't get loaded by Windows Explorer. This should eliminate the linker problem.

BOOL WINAPI DllMain(DWORD dwReason, LPVOID lpReserved) 
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        // Don't attach to Windows Explorer

        TCHAR pszLoader[MAX_PATH];
        GetModuleFileName(NULL, pszLoader, MAX_PATH);
        CString sLoader = pszLoader;
        sLoader.MakeLower();
        if (sLoader.Find(_T("explorer.exe")) >= 0)
            return FALSE;

        g_hinstPub = _AtlBaseModule.m_hInst;
    }
    return __super::DllMain(dwReason, lpReserved);
}
        

So now that we have our basic BHO, it would be nice to be able to exert some kind of control over it.  For starters, we need to be able to enable or disable it.  Also, it would be nice if Open in New Window from the context menu worked normally.  There are probably a number of ways to do this, but I chose to add my own menu to the normal IE context menu.  To access the IE context menu we need to derive from the IDocHostUIHandler interface and implement the ShowContextMenu method.

class ATL_NO_VTABLE CPub : 
    public IObjectWithSiteImpl<CPUB>,
    public IDispatchImpl,
    public IDocHostUIHandler
        

Add the ShowContextMenu method:

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

    return S_OK;
}
        

In order to get IE to call our ShowContextMenu we use the ICustomDoc::SetUIHandler method. Typically, this is done when we get the NavigateComplete2 event because at that point the document has been created and we can access the browsers IHTMLDocument2 interface. However, because we need to get the default handlers for IDocHostUIHandler and IOleCommandTarget (more on that later), instead we will do it in DocumentComplete after the entire document has been loaded. So we add a case to our Invoke method:

//

	// 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());
	{
		// Any new windows that might pop up after this

		// (due to script) should be blocked.

		m_bBlockNewWindow = TRUE;	// Reset


		if (!m_pWBDisp)
		{
			// This is the IDispatch* of the top-level browser

			m_pWBDisp = pDispParams->rgvarg[1].pdispVal;
		}
	}
	break;
	
case DISPID_DOCUMENTCOMPLETE:
	ATLTRACE(_T("(%ld) DISPID_DOCUMENTCOMPLETE\n"),
		::GetCurrentThreadId());
	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 spDisp;
		HRESULT hr = m_spWebBrowser2->get_Document(&spDisp);
		if (SUCCEEDED(hr) && spDisp)
		{
			// If this is not an HTML document (e.g., it's a

			// Word doc or a PDF), don't sink.

			CComQIPtr spHTML(spDisp);
			if (spHTML)
			{
			  // Get pointers to default interfaces

			  CComQIPtr spOleObject(spDisp);
			  if (spOleObject)
			  {
			    CComPtr spClientSite;
			    hr = spOleObject->GetClientSite(&spClientSite);
			    if (SUCCEEDED(hr) && spClientSite)
			    {
			      m_spDefaultDocHostUIHandler = spClientSite;
			      m_spDefaultOleCommandTarget = spClientSite;
			    }
			  }

			  // Set this class to be the IDocHostUIHandler

			  CComQIPtr spCustomDoc(spDisp);
			  if (spCustomDoc)
			    spCustomDoc->SetUIHandler(this);
			}
		} 
	}
	break;

If you compile and run now, you should see that the IE context menu is disabled since we are always returning S_OK from the ShowContextMenu method. In the MSDN documentation there is an excellent article titled "WebBrowser Customization" that explains exactly, with sample code, how to add code to ShowContextMenu so as to replicate the original IE context menu, so I won't bother to talk about all that here.  What the article did not explain was how to add your own menu to that context menu.  Create your menu resource and then add this menu to the top of the context menu in the normal fashion. Nothing tricky here:

// Insert our menu at the top of the context menu

g_hPubMenu = LoadMenu(g_hinstPub, MAKEINTRESOURCE(IDR_PUBMENU));
if (g_hPubMenu)
{
    ::InsertMenu(hSubMenu, 0, MF_POPUP | MF_BYPOSITION,
	(UINT_PTR) g_hPubMenu, _T("Popup Blocker"));
    ::InsertMenu(hSubMenu, 1, MF_BYPOSITION | MF_SEPARATOR, NULL, NULL);
}
        

The tricky part comes when you run the BHO and notice that the all the items on the context menu work as you expect EXCEPT for those items on your menu, which are disabled.  This is because IE inconveniently disregards menu items it does not recognize and will not enable your menu items even if you tell it to do so with the EnableMenuItem command.  To fix this, we need to temporarily add our own window procedure just before the call to TrackPopupMenu so that we can handle messages for our menu, then we restore the original window procedure immediately after TrackPopupMenu returns.

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_ENABLEPOPUPBLOCKER, MF_BYCOMMAND | (g_bEnabled ?
			MF_CHECKED : MF_UNCHECKED));
            ::CheckMenuItem(g_hPubMenu, ID_PLAYSOUND,
		MF_BYCOMMAND | (g_bPlaySound ? MF_CHECKED : MF_UNCHECKED));
            return 0;
        }
    }
    return CallWindowProc(g_lpPrevWndProc, hwnd, uMsg, wParam, lParam);
}
            

If a message is not for our menu, we just pass it on to the original window procedure.  Now that the menu is working, you can add switches and dialogs to control the behavior of the BHO. In the code included with this article I added a checked menu item to enable/disable the BHO.  I also intercepted the normal Open in New Window command and set a flag temporarily disabling the BHO in order to restore normal behavior.

So at this point we have a popup blocker that works pretty well, but there are still a couple of glitches.  The first one that you will notice is that certain links seem to be disabled, that is nothing happens when they are clicked.  These are links that  pop up another window, usually through a bit of script.  The BHO happily suppresses these windows with no indication to the user.  To solve this problem, I added a way to temporarily override the BHO by holding down the CTRL key. You have to be careful here to not disable the SHIFT + Click shortcut used to open a new window (thanks to Matt Newman for pointing that one out!).

BOOL CPub::IsHotkeyDown()
{
	SHORT nState = GetAsyncKeyState(VK_CONTROL);
	BOOL bDown = (nState & 0x8000);
	if (!bDown)
	{
		// Allow shift+click to open a new window

		nState = GetAsyncKeyState(VK_SHIFT);
		bDown = (nState & 0x8000);
	}
	return bDown;
}
            

But how is the user supposed to know when to press the hot key? In my code I chose to play a sound every time a popup window is suppressed. That way the user has an indication that the BHO is in the act when a link appears to be broken.  Then all the user needs to do is hold down the CTRL key while clicking the link, and the link will work normally.

Now our popup blocker is working really well.  It blocks all popup windows and we can shut it off if we need to.  However, there are still a couple of problems to solve and you probably won't notice them right away.  For one, when browsing the web you will start to see these IE Script Error dialogs popping up:

IE Script Error dialog

This is even more annoying than the normal popup ads.  They occur because some scripts expect to have the popup window available and generate an error when it is not.  Because not all script writers add error handlers to their pages, IE acts as the default error handler and poups up its own cryptic dialog box.  Another problem is that some options on the Save As dialog under "Save as type" have disappeared, and there are various other UI problems when hosting IE -- like scroll bars going away when viewing help inside Visual Studio. 

To solve script error problem, I implemented IOleCommandTarget and added the methods for QueryStatus and Exec.  If I get an OLECMDID_SHOWSCRIPTERROR in Exec, I set pvaOut to VARIANT_TRUE to indicate that I wish to continue running scripts and return S_OK instead of the default to suppress the script error dialog.

class ATL_NO_VTABLE CPub : 
	public IObjectWithSiteImpl<CPUB>,
	public IDispatchImpl,
	public IDocHostUIHandler,
	public IOleCommandTarget
			
STDMETHOD(QueryStatus)(
	/*[in]*/ const GUID *pguidCmdGroup, 
	/*[in]*/ ULONG cCmds,
	/*[in,out][size_is(cCmds)]*/ OLECMD *prgCmds,
	/*[in,out]*/ OLECMDTEXT *pCmdText)
{
	return m_spDefaultOleCommandTarget->QueryStatus(pguidCmdGroup, cCmds,
		prgCmds, pCmdText);
}
	
STDMETHOD(Exec)(
	/*[in]*/ const GUID *pguidCmdGroup,
	/*[in]*/ DWORD nCmdID,
	/*[in]*/ DWORD nCmdExecOpt,
	/*[in]*/ VARIANTARG *pvaIn,
	/*[in,out]*/ VARIANTARG *pvaOut)
{
	if (nCmdID == OLECMDID_SHOWSCRIPTERROR)
	{
		// Don't show the error dialog, but

		// continue running scripts on the page.

		(*pvaOut).vt = VT_BOOL;
		(*pvaOut).boolVal = VARIANT_TRUE;
		return S_OK;
	}
	return m_spDefaultOleCommandTarget->Exec(pguidCmdGroup, nCmdID,
		nCmdExecOpt, pvaIn, pvaOut);
}
		

With our IOleCommandTarget implementation in place all unhandled script errors are gobbled up and the default IE Script Error dialogs never show up. 

I should mention that in my first implementation I was intercepting the HTMLWindowEvents2::onerror event which gets fired whenever an unhandled script error occurs.  It is indeed possible to do it that way, but you have to be careful to attach the handler to the top-level window.  If you attach to a child frame, then events in a sibling frame will not be caught (as pointed out by ferdo. Thanks!).  If you attach to the top-level window, then unhandled events will eventually bubble up to your handler.  In digging into that problem, I decided to scrap that method in favor of the IOleCommandTarget implementation just because I thought it was cleaner and easier to understand.

The Save As and UI problems are solved by simply calling the default handler from within each IDocHostUIHandler method . Using the pointer to the default handler we got during DISPID_DOCUMENTCOMPLETE, we call the default if we are not handling the method ourselves.

STDMETHOD(GetHostInfo)(DOCHOSTUIINFO FAR *pInfo)
{
	if (m_spDefaultDocHostUIHandler)
		return m_spDefaultDocHostUIHandler->GetHostInfo(pInfo);
	return S_OK;
}
		

It's not clear why these UI problems are not mentioned in MSDN documentation on BHOs (if they are, I missed them),  but they definately should be.

<shameless_plug>The latest version can be installed from the web at Osborn Technologies.</shameless_plug>

Improvements

There is still room for a number of improvements:

Revision History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralIe requests
Radu_20
21:45 22 Oct '09  
Is there any way in which I could hook Ie requests in my application. I want to do this to filer out unwanted content ... for example flash player requests.

Thanks,
Radu


GeneralCan we use this to block javascript alert?
My2Cents
12:30 27 Jul '09  
Any ideas?
Generalwindow popup
kishorg1
20:19 4 Sep '08  
i want window popup on text box TextChanged event
my text box is in gridview.

<ItemTemplate>
<%--<%--<%--<input id="txtbxStartDate" runat="server" type="text" />--%>
<asp:TextBox ID="txtbxStartDate" runat="server" Style="width: 70px"
OnTextChanged="txtbxStartDate_TextChanged"></asp:TextBox>
<asp:ImageButton ID="imgStrtDt" runat="server" TabIndex="9" Height="21px" ImageUrl="../Images/calecder.jpg"
AlternateText="SelectDate" OnClientClick="return false;" />
<ajaxToolkit:CalendarExtender ID="clndrStrtDt" runat="server" Format="MM/dd/yyyy"
TargetControlID="txtbxStartDate" PopupButtonID="imgStrtDt">
</ajaxToolkit:CalendarExtender>
</ItemTemplate>
that is the code .......

protected void txtbxStartDate_TextChanged(object sender, EventArgs e)
{
objclsBizWorkPlan = new clsBizWorkPlan();
if (C1gdvAssignProcess.Items.Count > 0)
{
for (int i = 0; i < C1gdvAssignProcess.Items.Count; i++)
{
if (((CheckBox)C1gdvAssignProcess.Items[i].Cells[0].FindControl("ChkSelectProcess")).Checked)
{
string SDate = ((TextBox)C1gdvAssignProcess.Items[i].Cells[4].FindControl("txtbxStartDate")).Text.ToString();
htxtHidden.Value = SDate;
string StartDate = htxtHidden.Value;
int Assignedto = Convert.ToInt32(((DropDownList)C1gdvAssignProcess.Items[i].Cells[3].FindControl("dduser")).SelectedValue);

DataTable dtUserDetails = objclsBizWorkPlan.GetUserDetails(Assignedto, StartDate);

string status = Convert.ToString(dtUserDetails.Rows[0]["status"]);
string processname = Convert.ToString(dtUserDetails.Rows[0]["processname"]);
string coname = Convert.ToString(dtUserDetails.Rows[0]["coname"]);
DateTime sdate = Convert.ToDateTime(dtUserDetails.Rows[0]["startdate"].ToString());

string strQueryString = "Status=" + status + "&ProcessName=" + processname + "&CoName=" + coname + "&SDate=" + sdate;
Response.Write("<script type='text/javascript'>window.open('frmpopup.aspx?" + strQueryString + "','height=800,width=800′);</script>");
//ClientScript.RegisterStartupScript(this.GetType(), "PopupWindow", "int w=window.open('frmpopup.aspx','height=800,width=800′);");
}
}//for
}//if
}

this code is not working............above event is not get call
Generalhello
jiqihuman
7:19 12 Jun '08  
hello
GeneralIOleCommandTarget
shawkins
14:52 17 Jul '07  
I still getting the scripting errors even though IOleCommandTarget has been implemented. I have tried it in my own BHO and in this sample project and I get the same results. Any help with this would be aprreciated.

Thanks,
S Hawkins
GeneralHow about vista?
yecheng_beyond
19:56 4 Mar '07  
There is no file named "shdoclc.dll" in vista.
GeneralRe: How about vista?
Crulex
17:54 14 Jul '07  
Have anyone found a solution for dynamically adding context menu entries in Vista and Win98?
I've tried installing your popup blocker and it crashes under those OS.

I'm having the same problems with my IE toolbar (as I've used your code for adding menu entries - thanks a lot). I need 64-bit support, too.
I wonder if it would be easier to use registry for adding a popup menu entry to IE (fortunately I need only 1 menu item) - but I'll need to implement the required COM interfaces in my toolbar, to respond to the the menu item click event.

Thanks in advance for any comments on the above
GeneralRe: How about vista?
yecheng_110
16:15 15 Jul '07  
look here
http://www.codeguru.com/Cpp/COM-Tech/atl/atl/article.php/c11007
GeneralRe: How about vista?
Crulex
16:40 15 Jul '07  
Thanks!
Still have to switch to using registry method then.
GeneralThe reason of the save as behavior change
JIANG, Sheng[MVP]
14:49 21 Apr '06  
Is the difference between SHDOCVW and MSHTML, and your overriding of IDocHostUIHandler. see http://spaces.msn.com/jiangsheng/blog/cns!1BE894DEAF296E0A!483.entry[^]

Regards

Microsoft MVP in Visual C++

http://blog.joycode.com/jiangsheng

-- modified at 19:49 Friday 21st April, 2006
GeneralMemory Leak
Lonnie Johnson
5:41 17 Aug '05  
I have adapted the context menu code of Popup Window Block to add menu items to the IE context menu for my BHO. I added the code to my BHOView class and my context menu items are added to the IE context menu and I can capture the menu selections. Everything seems to work correctly. However I deleloped a memory leak. The cause of the leak is that the destructor for BHOView is never called.

Commenting out the following lines from CBHOView::OnDocumentComplete
cures the leak, but of course I lose my addition to the context menu.

CComQIPtr spCustomDoc(spDispDoc);
if (spCustomDoc)
spCustomDoc->SetUIHandler(this);

Any idea what I am missing? I am baffled.
GeneralRe: Memory Leak
cKrishnamoorthy
21:06 7 Sep '05  
I get a similar error when I make a SetUIHandler() call. SetUIHandler seems to be generating a memory leak. Have not been able to figure out why?

krishna
GeneralRe: Memory Leak
Lonnie Johnson
5:56 8 Sep '05  
As I said in my prior e-mail my memory leak was the result of the destructor for my BHOView class not being called. It was the class that called SetUIHandler.

I found a solution to this problem. I caputred the default UIHandler interface and called that for any UIOHandler functions that I did not need to handle:

CBHOView::OnDoucmentComplete
...
// Get pointers to default interfaces
CComQIPtr spOleObject(spDispDoc);
if (spOleObject)
{
CComPtr spClientSite;
hr = spOleObject->GetClientSite(&spClientSite);
if (SUCCEEDED(hr) && spClientSite)
{
m_spDefaultDocHostUIHandler = spClientSite;
m_spDefaultOleCommandTarget = spClientSite;
}
}
// Set this class to be the IDocHostUIHandler
// Causes BHOView::ShowContextMenu to be called
CComQIPtr spCustomDoc(spHTMLDoc2);
if (spCustomDoc)
spCustomDoc->SetUIHandler(this);

Example of calling the default UIHandler:

STDMETHOD(GetHostInfo)(DOCHOSTUIINFO FAR *pInfo)
{
if (m_spDefaultDocHostUIHandler)
return m_spDefaultDocHostUIHandler->GetHostInfo(pInfo);
return S_OK;
}

Here is the discussion site where I found the solution:

http://groups.google.com/group/microsoft.public.inetsdk.programming.webbrowser_ctl/browse_thread/thread/b44d7d748175ba88/f6da167bd2c4482b?lnk=st&q=IOleClientSite+BHO&rnum=9&hl=en#f6da167bd2c4482b[^]

I hope this helps.
GeneralRe: Memory Leak
Lonnie Johnson
5:56 8 Sep '05  
As I said in my prior e-mail my memory leak was the result of the destructor for my BHOView class not being called. It was the class that called SetUIHandler.

I found a solution to this problem. I caputred the default UIHandler interface and called that for any UIOHandler functions that I did not need to handle:

CBHOView::OnDoucmentComplete
...
// Get pointers to default interfaces
CComQIPtr spOleObject(spDispDoc);
if (spOleObject)
{
CComPtr spClientSite;
hr = spOleObject->GetClientSite(&spClientSite);
if (SUCCEEDED(hr) && spClientSite)
{
m_spDefaultDocHostUIHandler = spClientSite;
m_spDefaultOleCommandTarget = spClientSite;
}
}
// Set this class to be the IDocHostUIHandler
// Causes BHOView::ShowContextMenu to be called
CComQIPtr spCustomDoc(spHTMLDoc2);
if (spCustomDoc)
spCustomDoc->SetUIHandler(this);

Example of calling the default UIHandler:

STDMETHOD(GetHostInfo)(DOCHOSTUIINFO FAR *pInfo)
{
if (m_spDefaultDocHostUIHandler)
return m_spDefaultDocHostUIHandler->GetHostInfo(pInfo);
return S_OK;
}

Here is the discussion site where I found the solution:

http://groups.google.com/group/microsoft.public.inetsdk.programming.webbrowser_ctl/browse_thread/thread/b44d7d748175ba88/f6da167bd2c4482b?lnk=st&q=IOleClientSite+BHO&rnum=9&hl=en#f6da167bd2c4482b[^]

I hope this helps.
Generalhow about VC++ 6.0 ?
dupasmoka
11:03 17 Mar '05  
Can I do the same with VC++ 6.0 compiler?
GeneralBHO in custom application only
manuelricca
9:28 23 Feb '05  
First of all thank you very much for this code.
I would like to use block popups in a custom application that hosts web browser objects. I don't want to change any of IE's behaviour or add any menus, but I want my own applications to have an option to block popups.
Does anyone have any idea on how to do this? Maybe by using the same method as for the explorer.exe restriction?

Thanks in advance!
MR
GeneralAnti Popup Blocker
san80
1:08 27 Dec '04  
Hello,
I have Anti popup working fine with IE6.0 but it crashes IE5.5 when blocking the pop-ups.

Problem in

pDispParams->rgvarg[0].pvarVal->vt = VT_BOOL;
pDispParams->rgvarg[0].pvarVal->boolVal = VARIANT_TRUE;

Please let me know if there is anyway to work around it?

Thanks a lot!
Sandy

GeneralProblem with BHO through windows explorer
stroggoff
12:09 14 Dec '04  
Hello,

I am having this major problem with a test BHO I wrote. I mostly followed your example code. Now, when I load Internet Explorer directly, the BHO dll attaches itself to IE as it should and everything works well. And if I load the Windows Explorer the BHO is not attached (as it also should).

However, if I load first the "explorer.exe" window, then write a url in the address field and press "Go", the Windows OS changes the Windows explorer interface to Internet Explorer Interface, but the BHO is NOT loaded. Is there a way around this WITHOUT attaching the dll to the explorer.exe too ? (Ofcourse attaching the dll to explorer.exe solves the problem but it is VERY drastic and it causes the linking troubles you mention)

Any help is appreciated,
Thank you
Generalmemory leak?
gbadauy
16:02 13 Oct '04  
I've made some changes on the CPub class, and it creates a leak of the CPub *.
It's only 44 bytes long, but still it's leaking...
Does anyone have any ideas on how to fix it?
GeneralHow to use this dll ?
ptmhanh
23:09 6 Sep '04  
I want to block, unblock popup in IE. Please tell me how to use PopupBlocker.dll in asp.net solution.
Thank you.

hanh
GeneralIt crashed IE5.5 when blocking the pop-up
guoalan
9:47 23 Jul '04  
It is a good program. I registred on Win98 system with IE5.5 on it.

But it crashed IE5.5 when blocking the pop-ups. I did some debuging that found out the following two line code causing problems:

pDispParams->rgvarg[0].pvarVal->vt = VT_BOOL;
pDispParams->rgvarg[0].pvarVal->boolVal = VARIANT_TRUE;

Please let me know if there is anyway to work around it?

IE6 has no problem at all.

Thanks a lot!

Alan
GeneralRe: It crashed IE5.5 when blocking the pop-up
John Osborn
7:17 24 Jul '04  
That fix is in the new version which is somewhere else on CP.
However, that new version will not work on Win98.
GeneralCrash with Win XP SP2 RC
LukeV
3:22 12 Jul '04  
Hi,

perhaps it's the SP2 RC fault, but I get a crash with this code:

Invoke(...)
{
case DISPID_NEWWINDOW2:
{
pDispParams->rgvarg[0].pvarVal->vt = VT_BOOL;
pDispParams->rgvarg[0].pvarVal->boolVal = VARIANT_TRUE;
}
break;
}

It crashes in shdocvw.dll
GeneralRe: Crash with Win XP SP2 RC
PronayDutta
14:06 25 Aug '04  
Yup it crashes on SP2. It should be just

*(pDispParams->rgvarg[0].pboolVal) = VARIANT_TRUE;

You can also set the pDispParams->rgvarg[1].pdispatch to your browser's dispatch pointer.

Good luck
Pronay

Pronay
GeneralBlock Pop
anonymous
21:49 16 Jun '04  
Im getting the IHTMLDocument2 pointer using the following way,
CoCreateInstance( CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER,
IID_IHTMLDocument2,( void** ) &pDoc );
How do I block the popup, with a valid pDoc pointer... Without really implementing IOleClientSite, IDispatch.


Last Updated 2 May 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010