1. 程式人生 > >DockPanel與GeckoFX、ChrominumFX、CefSharp結合使用問題

DockPanel與GeckoFX、ChrominumFX、CefSharp結合使用問題

ble static bject == tin default chang itl left

在使用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);
};

至此,可解決瀏覽器控件崩潰問題。

DockPanel與GeckoFX、ChrominumFX、CefSharp結合使用問題