在使用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. java Concurrent包学习笔记(一):ExecutorService

    一.介绍 ExecutorService是java.util.concurrent包中的一个线程池实现接口.其有两个实现类: 1)ThreadPoolExecutor:普通线程池通过配置线程池大小,能 ...

  2. Linux下通过管道杀死所有与tomcat相关的进程

    先将正确的命令放上来: ps -ef | grep ps -ef将系统中运行的进程展示出来 选择带有tomcat的进程后同时去除自身带有grep的进程,毕竟本身运行的这条命令是与tomcat相关的 a ...

  3. 时间控件My97简单用法

    my97的用法很是简单,项目中用到,查了资料才找到的,简单使用,记一下,方便查阅. 1.添加依赖. <script language="javascript" type=&q ...

  4. R语言的文件写入

    R语言的文件写入 官方文档介绍如下: write.table(x, file = "", append = FALSE, quote = TRUE, sep = " &q ...

  5. 2.2.10数据类型String的常量池特性

    在JVM中具有String常量池缓存的功能 package com.cky.test; /** * Created by edison on 2017/12/8. */ public class Te ...

  6. linux下的各个目录(待填)

    /系统目录 / 下的目录: 1./bin(binary,二进制文件):打开里面会发现全是绿色的文件,也就是可执行文件,而且名字都是系统命令的名字,其实每个系统命令都是一个小的可执行的文件,这些命令都存 ...

  7. Shell编程-12-Shell脚本规范及调试

    目录 Shell脚本规范 Shell脚本调试 Shell脚本规范     良好的代码规范不仅方便阅读,也利于维护和提升开发效率.因此建议大家在编写Shell脚本时养成良好的代码习惯.今天就和大家探讨一 ...

  8. codeforces 877b

    B. Nikita and string time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. codeblock快捷键使用

    •在编辑区按住右键可拖动代码,省去拉滚动条之麻烦:相关设置:Mouse Drag Scrolling. •Ctrl+D可复制当前行或选中块. •可拖动选中块使其移动到新位置,按住Ctrl则为复制到新位 ...

  10. hive函数 get_json_object的使用

    hive提供了json的解析函数:get_json_object 使用方法 对于jsonArray(json数组),如person表的xjson字段有数据: [{"name":&q ...