wpf webBrowser控件

wpf webBrowser 的控件 坑太多了 不推荐使用, 推荐使用winform webbrowser

在wpf中如何使用与扩展winform webbrowser,请看我的另一篇文章在wpf中使用winform webbrowser

介绍

WebBrowsers可以让我们在窗体中进行导航网页。
WebBrowser控件内部使用ie的引擎,因此使用WebBrowser我们必须安装ie浏览器(windows默认安装的)。

使用

直接在xmal中使用webBrowser控件

1
<WebBrowser x:Name="WebBrowser1" Source ="xxx.com"></WebBrowser>

 

其中Source熟悉可以将webBrowser控件指向一个网页(也可以是本地文件的绝对路径)
除了使用Source属性还有以下方法进行导航:

方法 用法

Navigate() 传入网页url WebBrowser1.Navigate(new Uri(address));
NavigateToString 传入html页面内容WebBrowser1.NavigateToString("<html><body></body></html > ");
GoBack() 导航到上一个文档,需要判断能否调用if (WebBrowser1.CanGoBack){WebBrowser1.GoBack();}
GoForward 导航到下一个文档if (WebBrowser1.CanGoForward){WebBrowser1.GoForward();}
Navigating 发生在导航到新的页面时发生,可以在这里取消导航 WebBrowser1.Navigating += (sender, args) ={args.Cancel = true;};
Navigated 导航之后,在下载web页面之前引发 WebBrowser1.Navigated += (sender, args) =>{Console.WriteLine("ed" + args?.Uri);};
LoadCompleteed 当web页面下载完成时引发这个事件,这时可以处理网页 WebBrowser1.LoadCompleted += (sender, args)=>{Console.WriteLine(WebBrowser1.Document);};

问题js报错

默认情况下webBrowser用的是比较低的ie内核,这样如果访问的网页有不支持的脚本或者其他问题,就会没有办法正常运行,比如报错 javaScript错误。某些情况下使用ie可以打开的网页,在webBrowser需要管理员权限才可以正常打开,没有管理员权限也会报jabaScript错误。所以一般使用winForm的webBrowser,方便扩展,并且资料多。

避免报错不弹提示框

1
2
3
4
WebBrowser1.Navigated += (sender, args) =>
{
     SetSilent(wbMain, true)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void SetSilent(WebBrowser browser, bool silent)
{
    if (browser == null)
     throw new ArgumentNullException("browser");
 
    // get an IWebBrowser2 from the document
    IOleServiceProvider sp = browser.Document as IOleServiceProvider;
    if (sp != null)
    {
        Guid IID_IWebBrowserApp = new Guid("0002DF05-0000-0000-C000-000000000046");
        Guid IID_IWebBrowser2 = new Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E");
 
        object webBrowser;
        sp.QueryService(ref IID_IWebBrowserApp, ref IID_IWebBrowser2, out webBrowser);
        if (webBrowser != null)
        {
         webBrowser.GetType().InvokeMember("Silent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.PutDispProperty, null, webBrowser, new object[] { silent });
        }
    }
}
[ComImport, Guid("6D5140C1-7436-11CE-8034-00AA006009FA"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface IOleServiceProvider
{
    [PreserveSig]
    int QueryService([In] ref Guid guidService, [In] ref Guid riid, [MarshalAs(UnmanagedType.IDispatch)] out object ppvObject);
}

这种只是让它不出现报错窗口,不能从根本上解决。

修改注册表使用新的ie内核,下面是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static void SetWebBrowserFeatures(int ieVersion)
   {
       if (LicenseManager.UsageMode != LicenseUsageMode.Runtime)
           return;
       var appName = System.IO.Path.GetFileName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
       UInt32 ieMode = GeoEmulationModee(ieVersion);
       var featureControlRegKey = @"HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\";
       Registry.SetValue(featureControlRegKey + "FEATURE_BROWSER_EMULATION",
           appName, ieMode, RegistryValueKind.DWord);
       Registry.SetValue(featureControlRegKey + "FEATURE_ENABLE_CLIPCHILDREN_OPTIMIZATION",
           appName, 1, RegistryValueKind.DWord);
   }
 
   static UInt32 GeoEmulationModee(int browserVersion)
   {
       UInt32 mode = 11000; // Internet Explorer 11. Webpages containing standards-based !DOCTYPE directives are displayed in IE11 Standards mode.
       switch (browserVersion)
       {
           case 7:
               mode = 7000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode.
               break;
           case 8:
               mode = 8000; // Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode.
               break;
           case 9:
               mode = 9000; // Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode.                   
               break;
           case 10:
               mode = 10000; // Internet Explorer 10.
               break;
           case 11:
               mode = 11000; // Internet Explorer 11
               break;
       }
       return mode;
   }

比如你想使用最新的IE11

1
SetWebBrowserFeatures(11);

在网页中强制以ie最高级别的可用模式显示内容

1
<meta http-equiv="X-UA-Compatible" content="edge" />

内存泄漏

Memory leak when using WPF WebBrowser control in multiple windows

内存泄漏的解决方式

不使用wpf中的 WebBrowser
将WebBrowser放到子进程中,每次开关都会重新分配内存
删除掉所有引用,来清理内存泄漏。关闭窗口时调用下面代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public void Dispose()
{
    webBrowser.Dispose();
 
    var window = GetWindowElement(webBrowser);
 
    if (window == null)
        return;
 
    var field = typeof(Window).GetField("_swh", BindingFlags.NonPublic | BindingFlags.Instance);
 
    var valueSwh = field.GetValue(window);
    var valueSourceWindow = valueSwh.GetType().GetField("_sourceWindow", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(valueSwh);
    var valuekeyboardInput = valueSourceWindow.GetType().GetField("_keyboardInputSinkChildren", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(valueSourceWindow);
 
    var inputSites = valuekeyboardInput as IEnumerable<IKeyboardInputSite>;
 
    if (inputSites == null)
        return;
 
    var currentSite = inputSites.FirstOrDefault(s => ReferenceEquals(s.Sink, webBrowser));
 
    if (currentSite != null)
        currentSite.Unregister();
}
 
private static Window GetWindowElement(DependencyObject element)
{
    while (element != null && !(element is Window))
    {
        element = VisualTreeHelper.GetParent(element);
    }
 
    return element as Window;
}

 

原文链接:https://blog.csdn.net/wodeshijianhrf/article/details/79907743

posted @   多见多闻  阅读(747)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示