在使用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行之后,增加如下代码:

 private static readonly object MdiParentChangingEvent = new object();
/// <summary>
/// 开始设置MdiParent之前事件
/// </summary>
public event EventHandler MdiParentChanging
{
add { Events.AddHandler(MdiParentChangingEvent, value); }
remove { Events.RemoveHandler(MdiParentChangingEvent, value); }
}
protected virtual void OnMdiParentChanging(EventArgs e)
{
EventHandler handler = (EventHandler)Events[MdiParentChangingEvent];
if (handler != null)
handler(this, e);
} private static readonly object MdiParentChangedEvent = new object();
/// <summary>
/// 设置MdiParent之后的事件
/// </summary>
public event EventHandler MdiParentChanged
{
add { Events.AddHandler(MdiParentChangedEvent, value); }
remove { Events.RemoveHandler(MdiParentChangedEvent, value); }
}
protected virtual void OnMdiParentChanged(EventArgs e)
{
EventHandler handler = (EventHandler)Events[MdiParentChangedEvent];
if (handler != null)
handler(this, e);
}

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

 private void SetPane(DockPane pane)
{
if (pane != null && pane.DockState == DockState.Document && DockPanel.DocumentStyle == DocumentStyle.DockingMdi)
{
if (Form.Parent is DockPane)
SetParent(null);
if (Form.MdiParent != DockPanel.ParentForm)
{
FlagClipWindow = true;
OnMdiParentChanging(EventArgs.Empty);
// The content form should inherit the font of the dock panel, not the font of
// the dock panel's parent form. However, the content form's font value should
// not be overwritten if it has been explicitly set to a non-default value.
if (PatchController.EnableFontInheritanceFix == true && Form.Font == Control.DefaultFont)
{ Form.MdiParent = DockPanel.ParentForm;
//Form.MdiParent = null;
Form.Font = DockPanel.Font;
}
else
{
Form.MdiParent = DockPanel.ParentForm;
//Form.MdiParent = null;
}
OnMdiParentChanged(EventArgs.Empty);
}
}
else
{
FlagClipWindow = true;
if (Form.MdiParent != null)
{
OnMdiParentChanging(EventArgs.Empty);
Form.MdiParent = null;
OnMdiParentChanged(EventArgs.Empty);
}
if (Form.TopLevel)
Form.TopLevel = false;
SetParent(pane);
}
}

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

  private static readonly object MdiParentChangingEvent = new object();
/// <summary>
/// 开始设置MdiParent之前事件
/// </summary>
public event EventHandler MdiParentChanging
{
add { Events.AddHandler(MdiParentChangingEvent, value); }
remove { Events.RemoveHandler(MdiParentChangingEvent, value); }
}
protected virtual void OnMdiParentChanging(EventArgs e)
{
EventHandler handler = (EventHandler)Events[MdiParentChangingEvent];
if (handler != null)
handler(this, e);
} private static readonly object MdiParentChangedEvent = new object();
/// <summary>
/// 设置MdiParent之后的事件
/// </summary>
public event EventHandler MdiParentChanged
{
add { Events.AddHandler(MdiParentChangedEvent, value); }
remove { Events.RemoveHandler(MdiParentChangedEvent, value); }
}
protected virtual void OnMdiParentChanged(EventArgs e)
{
EventHandler handler = (EventHandler)Events[MdiParentChangedEvent];
if (handler != null)
handler(this, e);
} private void DockHandler_MdiParentChanging(object sender, EventArgs e)
{
OnMdiParentChanging(e);
}
private void DockHandler_MdiParentChanged(object sender, EventArgs e)
{
OnMdiParentChanged(e);
}

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

  m_dockHandler.MdiParentChanging += new EventHandler(DockHandler_MdiParentChanging);
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);
};

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

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

  1. 关于CefSharp的坎坷之路

    项目背景: 公司的XX产品需要升级和以后支持多平台的使用.因为之前项目是由WPF实现的.目前以后想作为Html5来展示页面. 因为涉及到整体更改遇到的问题较多以及其他原因,所以只是内部内容区域先替换为 ...

  2. 在WPF中使用CefSharp嵌入浏览器

    日常开发中,我们需要将一些Web页面嵌入到桌面客户端软件中.下面我们使用CefSharp嵌入浏览器来实现. 首先先介绍一下CefSharp嵌入式浏览器,它是基于Google浏览器的一个组件,我们可以在 ...

  3. 黄聪:C#使用GeckoFx拦截监控Http数据

    找了整整两天,在大海捞针之后,终于在上古代码中找到了一个可用的.... 可以用喜极而泣来形容测试有效之后的心情!!! 跟cefsharp相比geckofx最大的优点就是模式更接近于IE,包括node. ...

  4. 【WPF】使用CefSharp嵌入HTML网页

    需求:WPF项目中要做用户的商铺主页,由于考虑到每个商家的主页布局各不相同,不能用XAML写死布局.最好的办法是WPF这边XAML写好一个容器,用户使用HTML可视化编辑器(比如这个)来准备好网页,输 ...

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

    在WPF中使用CefSharp嵌入浏览器   日常开发中,我们需要将一些Web页面嵌入到桌面客户端软件中.下面我们使用CefSharp嵌入浏览器来实现. 首先先介绍一下CefSharp嵌入式浏览器,它 ...

  6. Winform下CefSharp的引用、配置、实例与报错排除(源码)

    Winform下CefSharp的引用.配置.实例与报错排除 本文详细介绍了CefSharp在vs2013..net4.0环境下,创建Winfrom项目.引用CefSharp的方法,演示了winfro ...

  7. .net使用cefsharp开源库开发chrome浏览器(二)

    离上篇写介绍pc端的混合开发和为什么以cefsharp入手研究混合开发已经有好几天,一直忙,抽不出时间继续写怎么搭建cefsharp开发环境.其实没有时间是借口,一切都是懒,没有爱到深处. 今天继续写 ...

  8. CefSharp初识--把网页移到桌面

    在开发中我们可曾有过这样的需求,将某个网页嵌入到.Net应用中来,但Winform自带的web browser不怎么理想.CefSharp可以让我们在.Net应用中嵌入一个Chromium.它提供了W ...

  9. cefsharp设置默认语言

    cefsharp是不错的浏览器内核封装版本之一,默认语言是en-US,这个一直困扰着项目,项目好多处需修改,后来经多次尝试,才发现,原来设置默认语言这么简单. CefSharp.Settings se ...

随机推荐

  1. Codeforces Round #544 (Div. 3) dp + 双指针

    https://codeforces.com/contest/1133/problem/E 题意 给你n个数(n<=5000),你需要对其挑选并进行分组,总组数不能超过k(k<=5000) ...

  2. AttributeError: type object 'testClass' has no attribute 'testMothod'

    点击"Unittest for test_post_API.testClass"按钮,点击”Edit configuration...“,弹出对话框Run/Debug config ...

  3. 将excel中的数据填入word模板中-VBA

    首先将word模板中需要填写excel中数据的空白处用自己独特的字符串标记,比如   数据001  什么的.如下图: 这样,就可以用vba搜寻这些自己独特的标记来根据excel内容填充word了. 第 ...

  4. Arria10中的OCT功能

    OCT是什么? 串行(RS)和并行(RT) OCT 提供了 I/O 阻抗匹配和匹配性能.OCT 维持信号质量,节省电路板空 间,并降低外部组件成本. Arria 10 器件支持所有 FPGA 和 HP ...

  5. 调试问题集之——Max10中配置完成后程序不能运行

    CONF_DONE信号是一个双向信号并且是Open-Drain.在配置过程中和配置之前作为输出,且为低电平.配置完成之后CONF_DONE作为输入脚,因为Open-Drain,所以必须由外部拉高,但二 ...

  6. 【Java】Java批量文件打包下载zip

    网上看了很多,本文使用ant.jar中的org.apache.tools.zip,页面用js表单提交 代码供参考: ACTION: /*      * 另存为      */     @Request ...

  7. python计算机硬件基础以及变量常量常量池,解释器编译器比较,python的两种运行方式

    1.什么是编程语言 语言是一个事物与另外一个事物沟通的介质 编程语言是程序员与计算机沟通的介质 2.什么是编程 编程就是程序按照某种编程语言的语法规范将自己想要让计算机做的事情表达出来 表达的结果就是 ...

  8. 20169207《Linux内核原理及分析》第十三周作业

    第一周作业::对Linux的基本知识进行了了解,并对基本操作进行熟悉和应用. 第二周作业::了解了冯诺依曼体系结构.各种寄存器的功能和汇编指令的作用和功能. 第三周作业::这周主要了解了Linux系统 ...

  9. python标准库及其它应用

    一: sys模块的介绍: 程序如下: #coding:utf-8import sysprint sys.argv[0]print sys.argv[1]print sys.argv[2] 打开cmd窗 ...

  10. 《mysql必知必会》学习_sql文件导入数据库_20180724_欢

    解决问题1:MySQL中导入sql文件. 步骤1:show databases;#看看我有什么数据库 步骤2:use hh;#我要用hh这个数据库,返回database changed说明打开成功. ...