views:

254

answers:

2

I have an Internet Explorer Browser Helper Object (BHO), written in c#, and in various places I open forms as modal dialogs. Sometimes this works but in some cases it doesn't. The case that I can replicate at present is where IE is running javascript to open other child windows... I guess it's getting a bit confused somewhere....

The problem is that when I call:

(new MyForm(someParam)).ShowDialog();

the form is not modal, so I can click on the IE window and it gets focus. Since IE is in the middle of running my code it doesn't refresh and therefore to the user it appears that IE is hanging.

Is there a way of ensuring that the form will be opened as modal, ie that it's not possible for the form to be hidden behind IE windows.

(I'm using IE7.)

NB: this is a similar question to this post although that's using java. I guess the solution is around correctly passing in the IWin32Window of the IE window, so I'm looking into that.

+1  A: 

It wasn't my intention to answer my own question, but...

It seems that if you pass in the correct IWin32Window to the ShowDialog() method it works fine. The trick is how to get this. Here's how I did this, where 'siteObject' is the object passed in to the SetSite() method of the BHO:

IWebBrowser2 browser = siteObject as IWebBrowser2;
if (browser != null) hwnd = new IntPtr(browser.HWND);
(new MyForm(someParam)).ShowDialog(new WindowWrapper(hwnd));

...

// Wrapper class so that we can return an IWin32Window given a hwnd
public class WindowWrapper : System.Windows.Forms.IWin32Window
{
    public WindowWrapper(IntPtr handle)
    {
        _hwnd = handle;
    }

    public IntPtr Handle
    {
        get { return _hwnd; }
    }

    private IntPtr _hwnd;
}

Thanks to Ryan for the WindowWrapper class, although I'd hoped there was a built-in way to do this?

UPDATE: this won't work on IE8 with Protected Mode, since it's accessing an HWND outside what it should be. Instead you'll have to use the HWND of the current tab (or some other solution?), e.g. see .net example in this post for a way of getting that.

Rory
+2  A: 

Here's a more concise version of Ryan/Rory's WindowWrapper code:

internal class WindowWrapper : IWin32Window
{
    public IntPtr Handle { get; private set; }
    public WindowWrapper(IntPtr hwnd) { Handle = hwnd; }
}
gt