3

Using the WebBrowser control, I currently see no way to detect whether a Navigating event is triggered because of the main page's URL is being changed, or whether an IFRAME is loaded.

The Frame parameter is always empty, no matter which attributes I put to the IFRAME.

My question:

Is there any chance/trick to determine from within a Navigating event handler, whether the event was triggered by an IFRAME?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291

1 Answers1

3

Found out a workaround:

I had to implement the additional DWebBrowserEvents2 interface as described in this Code Project article to get additional events.

Then, I get notified in the BeforeNavigate2 event with more information.

I discovered that pDisp is an IWebBrowser2 interface and that the Parent property of that interface is NULL for top windows and non-NULL for (I)FRAMES.

This was sufficient to me so I could then write:

public class BrowserExtendedNavigatingEventArgs : CancelEventArgs
{
    // ...

    public bool IsInsideFrame
    {
        get
        {
            var wb = AutomationObject as UnsafeNativeMethods.IWebBrowser2;
            return wb != null && wb.Parent != null;
        }
    }

    // ...
}

Please note that you have to ensure that you call the IsInsideFrame property from the thread that created the web browser control, otherwise you might get access violation exceptions, just as described here:

"...All IE COM objects, including the webbrowser control, are Single Threaded Apartment objects. Which means, among other things, you can only access them from the thread on which they were created. If you need to use them from other threads, you need to marshall them using the GIT or CoMarshallInterThreadInterfaceInStream() and related functions..."

I hope this might help others, too.


Alternative solution

Since I got AccessViolationExceptions when accessing the wb.Parent, although I think I did everything correctly, I was looking for an alternative solution.

I found it in this Code Project article.

Basically the article uses an alternative way to determine the frame. It does it by comparing the references to the web browser control.

Pseudo code:

public void BeforeNavigate2(
    object pDisp,
    ref object url,
    ref object flags,
    ref object targetFrameName,
    ref object postData,
    ref object headers,
    ref bool cancel)
{
    // ...

    var isTopFrame = _browser._axIWebBrowser2.Equals(pDisp);

    // ...
}

My tests run successfully so far, I really do hope that I get no more of these frightening access violation exceptions.

Community
  • 1
  • 1
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291