在使用WPF浏览器控件时,如何覆盖ie的BeforeNavigate2? [英] How can I overlop ie's BeforeNavigate2 when using the WPF Browser Control?
问题描述
据我了解,WPF的Brwoser控件是对Active-X控件的包装.后者具有BeforeNavigate2方法,而我在WPF WebBrowser控件中找不到此方法.有办法解决这个问题吗?
As far as I understand, WPF's Brwoser control is a wrapper of the ie Active-X control. The later has a BeforeNavigate2 Method, while I don't find this in the WPF WebBrowser control. Is there a way I can work around this?
谢谢!马克
推荐答案
是.WPF的WebBrowser控件确实死了.最重要的是,它甚至被密封了.
Yes. The WebBrowser control of WPF is really braindead. On top of that it is even sealed.
您必须使用Windows.Forms的WebBrowser控件并将其嵌入WindowsFormsHost中.
You have to use the WebBrowser control of Windows.Forms and embed it in a WindowsFormsHost.
此外,您还必须从WebBrowser派生一个类并在其中进行一些COM魔术操作.
Additionally you have to derive a class from WebBrowser and do some COM magic in it.
像这样制作一个UserControl:
Make a UserControl like this:
<UserControl x:Class="MP.Assistant.WpfClient.DialogContentControls.WebBrowserHost"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:DialogContentControls="clr-namespace:MP.Assistant.WpfClient.DialogContentControls"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<Grid Name="BrowserHost">
<WindowsFormsHost>
<DialogContentControls:ExtendedWinFormsWebBrowser x:Name="WebBrowser" />
</WindowsFormsHost>
</Grid>
然后按如下所示修改Windows.Forms WebBrowser:
Then modify Windows.Forms WebBrowser like this:
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Windows.Forms;
namespace MP.Assistant.WpfClient.DialogContentControls
{
/// Imports the BeforeNavigate2 method from the OLE DWebBrowserEvents2
/// interface.
[ComImport]
[Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[TypeLibType(TypeLibTypeFlags.FHidden)]
public interface DWebBrowserEvents2
{
[PreserveSig]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
[DispId(250)]
void BeforeNavigate2([In] [MarshalAs(UnmanagedType.IDispatch)] object pDisp,
[In] [MarshalAs(UnmanagedType.Struct)] ref object URL,
[In] [MarshalAs(UnmanagedType.Struct)] ref object Flags,
[In] [MarshalAs(UnmanagedType.Struct)] ref object TargetFrameName,
[In] [MarshalAs(UnmanagedType.Struct)] ref object PostData,
[In] [MarshalAs(UnmanagedType.Struct)] ref object Headers,
[In] [Out] ref bool Cancel);
}
public class ExtendedWinFormsWebBrowser : WebBrowser
{
// Handles the NavigateError event from the underlying ActiveX
// control by raising the NavigateError event defined in this class.
AxHost.ConnectionPointCookie cookie;
ExtendedWinFormsWebBrowserEventHelper helper;
bool renavigating;
public ExtendedWinFormsWebBrowser()
{
AdditionalHeaders = new string[] {};
}
public string[] AdditionalHeaders { get; set; }
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void CreateSink()
{
base.CreateSink();
// Create an instance of the client that will handle the event
// and associate it with the underlying ActiveX control.
helper = new ExtendedWinFormsWebBrowserEventHelper(this);
cookie = new AxHost.ConnectionPointCookie(ActiveXInstance, helper, typeof (DWebBrowserEvents2));
}
[PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
protected override void DetachSink()
{
// Disconnect the client that handles the event
// from the underlying ActiveX control.
if (cookie != null)
{
cookie.Disconnect();
cookie = null;
}
base.DetachSink();
}
void OnBeforeNavigate2(object pDisp,
ref object url,
ref object flags,
ref object targetFrameName,
ref object postData,
ref object headers,
ref bool cancel)
{
if (!renavigating)
{
if (AdditionalHeaders.Length > 0)
{
headers += string.Join("\r\n", AdditionalHeaders) + "\r\n";
renavigating = true;
cancel = true;
Navigate((string)url, (string)targetFrameName, (byte[])postData, (string)headers);
}
}
else
{
renavigating = false;
}
}
#region Nested type: ExtendedWinFormsWebBrowserEventHelper
class ExtendedWinFormsWebBrowserEventHelper : StandardOleMarshalObject, DWebBrowserEvents2
{
readonly ExtendedWinFormsWebBrowser parent;
public ExtendedWinFormsWebBrowserEventHelper(ExtendedWinFormsWebBrowser parent)
{
this.parent = parent;
}
#region DWebBrowserEvents2 Members
public void BeforeNavigate2(object pDisp,
ref object URL,
ref object Flags,
ref object TargetFrameName,
ref object PostData,
ref object Headers,
ref bool Cancel)
{
parent.OnBeforeNavigate2(pDisp,
ref URL,
ref Flags,
ref TargetFrameName,
ref PostData,
ref Headers,
ref Cancel);
}
#endregion
}
#endregion
}
}
然后从您的代码隐藏中使用WebBrowser(其名称类似于XAML),并为AdditionalHeaders提供所需的值.
Then use WebBrowser (its named like that in XAML) from your code-behind and provide AdditionalHeaders with the required value.
这篇关于在使用WPF浏览器控件时,如何覆盖ie的BeforeNavigate2?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!