WPF WebBrowser: How I do access progress and new w

2019-06-01 09:35发布

问题:

I'm building an a WPF app that uses the WebBrowser control.
I'm struggling on a couple of points:

  1. How to get the current progress of a download from the control. The WinForms WebBrowser control raises ProgressChange events - how can I replicate this feature with the WPF variant?

  2. How to capture links that are trying to open in a new window. Again the Winforms WebBrowser had a NewWindow event. I could use this to stop IE being started and to open the link in the same window. Is it possible to do this with the WPF variant?

回答1:

Having found the information I wanted I thought I'd update this question for anyone interested.

At the bottom of http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser(v=VS.90).aspx there is a comment entitled "Getting to the native IWebBrowser2".

This shows how to get to the required interface and seems to works well.

EDIT: Adding content of the link here as the comments at MSDN keep disappearing on me..

There is much functionality of the native Web Browser control that our managed wrapper does not yet expose. The following code snippet shows how to get the IWebBrowser2 interface from the WPF WebBrowser control. This allows access to methods on the object that are not publicly exposed in other ways for the control. Do note, however, that this code sample will only work in fully trusted code.

First, see IWebBrowser2 documentation here: http://msdn.microsoft.com/en-us/library/aa752127.aspx ...

To compile this code, add a COM Reference to System32\shdocvw.dll or ieframe.dll (whichever you have, depending on version of IE).

[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
internal interface IServiceProvider
{
    [return: MarshalAs(UnmanagedType.IUnknown)]
    object QueryService(ref Guid guidService, ref Guid riid);
}

static readonly Guid SID_SWebBrowserApp = 
      new Guid("0002DF05-0000-0000-C000-000000000046");

// ...

IServiceProvider serviceProvider = (IServiceProvider)myWebBrowser.Document;
Guid serviceGuid = SID_SWebBrowserApp;

Guid iid = typeof(SHDocVw.IWebBrowser2).GUID;

SHDocVw.IWebBrowser2 myWebBrowser2 = 
  (SHDocVw.IWebBrowser2) serviceProvider.QueryService(ref serviceGuid, ref iid);

And then myWebBrowser2 is ready for interaction.

You can also handle the native web browser's events (http://msdn.microsoft.com/en-us/library/aa768309(VS.85).aspx) through the generated managed wrappers, like this:

SHDocVw.DWebBrowserEvents_Event wbEvents = (SHDocVw.DWebBrowserEvents_Event)myWebBrowser2;
wbEvents.NewWindow += new SHDocVw.DWebBrowserEvents_NewWindowEventHandler(OnWebBrowserNewWindow);

void OnWebBrowserNewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
{
    // Set Processed to cancel opening of the new window.
}


回答2:

To get IWebBrowser2 interface, there is an easy way:

//The "browser" is a object of WebBrowser class.
SHDocVw.IWebBrowser2 axBrowser = typeof(WebBrowser).GetProperty("AxIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(browser, null) as SHDocVw.IWebBrowser2;

((SHDocVw.DWebBrowserEvents_Event)axBrowser).NewWindow += OnWebBrowserNewWindow;

private void OnWebBrowserNewWindow(string URL, int Flags, string TargetFrameName, ref object PostData, string Headers, ref bool Processed)
        {
            Processed = true;
            browser.Navigate(URL);
        }

The WebBrowser class has a property AxIWebBrowser2, and it holds the underlying COM browser object, but it is "internal", so we can get it by reflection.