问题在于,虽然WinForm和WPF的
WebBrowser
都只是相对较薄的包装器,用于控制ActiveX IE控件,但它们并没有向我们公开所有感兴趣的事件(第二个提供的比第一个还少)。解决这个问题有两种方法:第一种是子类化WF浏览器控件并添加所需内容,或者使用WPF控件并在那里添加钩子。我发现在WPF应用程序中采用第二种方法更加方便。
您只需要相关接口。最简单的方法是添加对Microsoft Internet Controls的引用(您可以在VS的COM标题下找到它)。这将打开一个名为SHDocVw
的命名空间,其中包含我们所需的所有内容(如果出于任何原因,您想摆脱此依赖项,可以将所使用的P / Invoke接口简单地复制到自己的代码中)。
您可以使用反射获取底层浏览器。如果您过早调用它,它将返回null
,因此我将其放入WebBrowser.Navigating
处理程序中:
using SHDocVw;
var ActiveXInstance = (IWebBrowser2)Browser.GetType().InvokeMember("ActiveXInstance", BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, Browser, new object[] { });
一旦您获得它,您可以在浏览器中做很棒的事情。例如,您可以使用各种属性和方法,这些属性和方法不是直接公开的:
ActiveXInstance.Silent = true
并添加缺失的事件钩子:
var SetupEvents2 = (DWebBrowserEvents2_Event)ActiveXInstance
SetupEvents2.BeforeNavigate2 += OnBeforeNavigate2
有两种事件接口,
2
变体包含更新的事件。您可以在
MSDN上查找所有这些信息。
回到标题:
BeforeNavigate2
事件允许您将额外的标头放入提供的对象中:
private void OnBeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel) {
Headers = $"Accept-Language: XX;en\r\n";
}