DockPanel与GeckoFX、ChrominumFX、CefSharp结合使用问题

在使用DockPanel与ChrominumFx时,当在以下条件下拖动窗体时,会发生ChromiumWebBrowser崩溃的情况,此种情况也会在DockPanel与GeckoFX或CefSharp结合使用时出现。

出现条件:

  1. 当Form表单初始时以DockState.Document,然后拖动此表单到非DockState.Document模式时,可以是DockState.Left、DockState.Right或其他。
  2. 当Form表单初始时以非DockState.Document时,然后拖动此表单到DockState.Document模式时

条件总结:即DockState.Document与其他模式切换时,会出现浏览器控件崩溃的情况。

出现此问题原因是DockPanel动态改变了Form表单的MdiParent,严格来说,并不是DockPanel的问题,如果直接使用Winform的MDI窗口模式,只要改变Form表单的MdiParent,也会导致浏览器控件崩溃。

为什么出现这个原因,目前并未深入分析,主要是也不知道从哪里开始分析,因为只是使用GeckoFX、ChrominumFX、CefSharp第三方浏览器控件才会出现此问题,而.NET 自带的WebBrowser没有此问题。

解决办法:

修改DockPanel部分源码,核心思路是在设置MdiParent之前,把浏览器控件从Form表单移除,设置之后,再把浏览器控件加入Form表单。

修改源码地方(修改的DockPanel版本是:2.13):

在DockContentHandler.CS类中 1053行之后,增加如下代码:

 1 private static readonly object MdiParentChangingEvent = new object();
 2         /// <summary>
 3         /// 开始设置MdiParent之前事件
 4         /// </summary>
 5         public event EventHandler MdiParentChanging
 6         {
 7             add { Events.AddHandler(MdiParentChangingEvent, value); }
 8             remove { Events.RemoveHandler(MdiParentChangingEvent, value); }
 9         }
10         protected virtual void OnMdiParentChanging(EventArgs e)
11         {
12             EventHandler handler = (EventHandler)Events[MdiParentChangingEvent];
13             if (handler != null)
14                 handler(this, e);
15         }
16
17         private static readonly object MdiParentChangedEvent = new object();
18         /// <summary>
19         /// 设置MdiParent之后的事件
20         /// </summary>
21         public event EventHandler MdiParentChanged
22         {
23             add { Events.AddHandler(MdiParentChangedEvent, value); }
24             remove { Events.RemoveHandler(MdiParentChangedEvent, value); }
25         }
26         protected virtual void OnMdiParentChanged(EventArgs e)
27         {
28             EventHandler handler = (EventHandler)Events[MdiParentChangedEvent];
29             if (handler != null)
30                 handler(this, e);
31         }

修改 DockContentHandler.CS类 785行的SetPane方法

 1 private void SetPane(DockPane pane)
 2         {
 3             if (pane != null && pane.DockState == DockState.Document && DockPanel.DocumentStyle == DocumentStyle.DockingMdi)
 4             {
 5                 if (Form.Parent is DockPane)
 6                     SetParent(null);
 7                 if (Form.MdiParent != DockPanel.ParentForm)
 8                 {
 9                     FlagClipWindow = true;
10                     OnMdiParentChanging(EventArgs.Empty);
11                     // The content form should inherit the font of the dock panel, not the font of
12                     // the dock panel‘s parent form. However, the content form‘s font value should
13                     // not be overwritten if it has been explicitly set to a non-default value.
14                     if (PatchController.EnableFontInheritanceFix == true && Form.Font == Control.DefaultFont)
15                     {
16
17                         Form.MdiParent = DockPanel.ParentForm;
18                         //Form.MdiParent = null;
19                         Form.Font = DockPanel.Font;
20                     }
21                     else
22                     {
23                         Form.MdiParent = DockPanel.ParentForm;
24                         //Form.MdiParent = null;
25                     }
26                     OnMdiParentChanged(EventArgs.Empty);
27                 }
28             }
29             else
30             {
31                 FlagClipWindow = true;
32                 if (Form.MdiParent != null)
33                 {
34                     OnMdiParentChanging(EventArgs.Empty);
35                     Form.MdiParent = null;
36                     OnMdiParentChanged(EventArgs.Empty);
37                 }
38                 if (Form.TopLevel)
39                     Form.TopLevel = false;
40                 SetParent(pane);
41             }
42         }

修改DockContent.CS类,在317行以后增加:

 1  private static readonly object MdiParentChangingEvent = new object();
 2         /// <summary>
 3         /// 开始设置MdiParent之前事件
 4         /// </summary>
 5         public event EventHandler MdiParentChanging
 6         {
 7             add { Events.AddHandler(MdiParentChangingEvent, value); }
 8             remove { Events.RemoveHandler(MdiParentChangingEvent, value); }
 9         }
10         protected virtual void OnMdiParentChanging(EventArgs e)
11         {
12             EventHandler handler = (EventHandler)Events[MdiParentChangingEvent];
13             if (handler != null)
14                 handler(this, e);
15         }
16
17         private static readonly object MdiParentChangedEvent = new object();
18         /// <summary>
19         /// 设置MdiParent之后的事件
20         /// </summary>
21         public event EventHandler MdiParentChanged
22         {
23             add { Events.AddHandler(MdiParentChangedEvent, value); }
24             remove { Events.RemoveHandler(MdiParentChangedEvent, value); }
25         }
26         protected virtual void OnMdiParentChanged(EventArgs e)
27         {
28             EventHandler handler = (EventHandler)Events[MdiParentChangedEvent];
29             if (handler != null)
30                 handler(this, e);
31         }
32
33         private void DockHandler_MdiParentChanging(object sender, EventArgs e)
34         {
35             OnMdiParentChanging(e);
36         }
37         private void DockHandler_MdiParentChanged(object sender, EventArgs e)
38         {
39             OnMdiParentChanged(e);
40         }

在 DockContent.CS类 14 行以后增加:

1  m_dockHandler.MdiParentChanging += new EventHandler(DockHandler_MdiParentChanging);
2  m_dockHandler.MdiParentChanged += new EventHandler(DockHandler_MdiParentChanged);

最后,在你的Form表单构造函数那里增加:

this.MdiParentChanging += (o, e) => {
    this.Controls.Remove(this.MainWebBrowser);
};
this.MdiParentChanged += (o, e) => {
    this.Controls.Add(this.MainWebBrowser);
};

至此,可解决浏览器控件崩溃问题。

时间: 2024-08-10 02:22:14

DockPanel与GeckoFX、ChrominumFX、CefSharp结合使用问题的相关文章

C#Winform下使用WebKit、Geckofx、CefSharp心得

最近公司需要从一个电商后台获取数据,无奈这项艰巨的任务交给了我,我查看了该站所有API都找不到相关的方法,找客服也无济于事,所以只有自己爬数据了.试了下python确实可以抓取cookie,无奈自己python新手.所以还是从最熟悉的winform入手.然后遇到了大坑,用遍这么多浏览器都无法抓到所有的cookies. 浏览器 内核 兼容 获取cookies VS自带webBrowser IE 最差 不全 WebKit Firefox 一般 不全 Geckofx Firefox 好 不全 CefS

WinForm中内嵌WebBroswer

本文系原创. 前两天在工作中需要在Winform的窗体中内嵌的一个浏览器,我们都知道winform其实是自带了WebBroswer控件的,但是这个控件是IE的浏览器,存在这样那样的兼容性问题,不能完全满足的需求,所以就研究了下其他的开源浏览器框架,内嵌到我们的窗体中,完成了产品需求,以下做一个记录和分享. 由于产品是要做商用的,所以必须得考虑开源性和开源协议的问题.研究了Geckofx.CefSharp这两个组件,其中Geckofx的开源许可证为MPL,CefSharp开源许可证为BSD. Ce

在WPF中使用CefSharp嵌入浏览器

日常开发中,我们需要将一些Web页面嵌入到桌面客户端软件中.下面我们使用CefSharp嵌入浏览器来实现. 首先先介绍一下CefSharp嵌入式浏览器,它是基于Google浏览器的一个组件,我们可以在WPF/WinForm客户端软件中使用它.CefSharp的代码托管在GitHub上,.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework. 目前最新版本的CefSharp是41.0版本,如果你的客户端软件

在WPF中使用CefSharp嵌入浏览器(转)

在WPF中使用CefSharp嵌入浏览器 日常开发中,我们需要将一些Web页面嵌入到桌面客户端软件中.下面我们使用CefSharp嵌入浏览器来实现. 首先先介绍一下CefSharp嵌入式浏览器,它是基于Google浏览器的一个组件,我们可以在WPF/WinForm客户端软件中使用它.CefSharp的代码托管在GitHub上,.NET (WPF and Windows Forms) bindings for the Chromium Embedded Framework. 目前最新版本的CefS

WPF使用cefsharp

最近在公司项目上会用到cefsharp.wpf,不知道为什么按照网上的配置一直无法运行成功,怎么配置可以参考以下这篇博文: http://www.cnblogs.com/TianFang/p/4573324.html 他的配置神马都是对的,为什么我在公司就一直运行不起来呢,各种百度.google,还是不行.后来到github上去下载(https://github.com/cefsharp/CefSharp)cefsharp的源代码,我用vs2010打开提示该工程是由更高版本的vs创建的,问题找到

Winform中DockPanel(引用WeifenLuo.WinFormsUI.Docking.dll组件)的使用

WeiFenLuo.WinFormsUI.Docking.dll是开源项目DockPanel Suite的一个类库,可实现像Visual Studio的窗口停靠.拖拽等功能.WeifenLuo.WinFormsUI.Docking是一个很强大的界面布局控件,可以保存自定义的布局为XML文件,可以加载XML配置文件.DockPanel中提供了几个可用的类,重要的有两个:DockPanel和DockContent.DockPanel是从Panel继承出来的,用于为可浮动的dock的子窗口提供进行浮动

ArcGIS AddIN 之 DockPanel 界面空白

辛辛苦苦写了个AddIn插件,自己用一切正常,发给别人就弹不出DockPanel, 或者弹出时只有Panel,没有具体的控件.经多次排查,原因是: 使用了第三方的界面控件DotNetBar,开发环境中由于DotNetBar配置正常,所以一切正常, 而其他人电脑没有DotNetBar,所以导致了DockPanel空白. 解决方法:电脑上装DotNetBar 控件

cefSharp 设置运行时系统语言

在使用用CefSharp使用过程中,系统用了很多第三方控件.这些控件很多能够根据浏览器设置的语言来进行控件展示对应语言. 在cefSharp可以设置系统语言,代码如下: CefSharp.Settings setting = new CefSharp.Settings(); string flashPath = Application.StartupPath+ @"\Plug\gcswf32.dll"; setting.AddPluginPath(flashPath); //设置语言

[Winform]CefSharp ——js调用c#方法

摘要 有时我们在winform中嵌入浏览器,需要在页面上读取电脑上的一些信息,这个时候就需要用到CefSharp的RegisterJsObject进行注册方法然后供js进行调用了. 一个例子 我们在winform中嵌入的页面中,显示电脑的信息,电脑信息通过winform进行读取,js调用获取电脑信息的方法,并将最终结果以json字符串的形式传递到js端,js获取到这些信息并在页面上进行显示. 定义一个专门处理js回调的类 /// <summary> /// js c#回调类 /// </