首页 > 代码库 > DockPanel与GeckoFX、ChrominumFX、CefSharp结合使用问题

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 MdiParentChanged22         {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 of12                     // the dock panel‘s parent form. However, the content form‘s font value should13                     // 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                     else22                     {23                         Form.MdiParent = DockPanel.ParentForm;24                         //Form.MdiParent = null;25                     }26                     OnMdiParentChanged(EventArgs.Empty);27                 }28             }29             else30             {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 MdiParentChanged22         {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);};

 

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

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