Skip to content

Commit 3dc37b2

Browse files
authored
WinForms - Add LifeSpanHandler implementation capable of hosting popups as Tabs/Controls (#3529)
* WinForms - Add LifeSpanHandler implementation capable of hosting popups as Tabs/Child controls in WinForms - Update Example - Remove PopupAsChildHelper and example LifeSpanHandler - Examples always opens popups as tabs now. - Improve xml doc and comments - Make ParentFormMessageInterceptor public - Make ChromiumHostControl public, move into CefSharp.WinForms.Host namespace Rather than having the class in the CefSharp.WinForms namespace and potentially confuse users, move into it's own namespace. - Clarify ShowDevToolsDocked needs to be used with the new WinForms lifespan handler
1 parent 2371370 commit 3dc37b2

13 files changed

+589
-617
lines changed

CefSharp.WinForms.Example/BrowserTabUserControl.cs

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
using CefSharp.Example.JavascriptBinding;
1414
using CefSharp.WinForms.Example.Handlers;
1515
using CefSharp.WinForms.Experimental;
16+
using CefSharp.WinForms.Handler;
1617

1718
namespace CefSharp.WinForms.Example
1819
{
@@ -53,10 +54,49 @@ public BrowserTabUserControl(Action<string, int?> openNewTab, string url, bool m
5354
browser.FocusHandler = null;
5455
}
5556

56-
//Handling DevTools docked inside the same window requires
57-
//an instance of the LifeSpanHandler all the window events,
58-
//e.g. creation, resize, moving, closing etc.
59-
browser.LifeSpanHandler = new LifeSpanHandler(openPopupsAsTabs: false);
57+
//The CefSharp.WinForms.Handler.LifeSpanHandler implementation
58+
//allows for Popups to be hosted in Controls/Tabs
59+
//This example also demonstrates docking DevTools in a SplitPanel
60+
browser.LifeSpanHandler = LifeSpanHandler
61+
.Create()
62+
.OnPopupCreated((ctrl, targetUrl) =>
63+
{
64+
//Don't try using ctrl.FindForm() here as
65+
//the control hasn't been attached to a parent yet.
66+
if (FindForm() is BrowserForm owner)
67+
{
68+
owner.AddTab(ctrl, targetUrl);
69+
}
70+
})
71+
.OnPopupDestroyed((ctrl, popupBrowser) =>
72+
{
73+
//If we docked DevTools (hosted it ourselves rather than the default popup)
74+
//Used when the BrowserTabUserControl.ShowDevToolsDocked method is called
75+
if (popupBrowser.MainFrame.Url.Equals("devtools://devtools/devtools_app.html"))
76+
{
77+
//Dispose of the parent control we used to host DevTools, this will release the DevTools window handle
78+
//and the ILifeSpanHandler.OnBeforeClose() will be call after.
79+
ctrl.Dispose();
80+
}
81+
else
82+
{
83+
//If browser is disposed or the handle has been released then we don't
84+
//need to remove the tab in this example. The user likely used the
85+
// File -> Close Tab menu option which also calls BrowserForm.RemoveTab
86+
if (!ctrl.IsDisposed && ctrl.IsHandleCreated)
87+
{
88+
if (ctrl.FindForm() is BrowserForm owner)
89+
{
90+
var windowHandle = popupBrowser.GetHost().GetWindowHandle();
91+
92+
owner.RemoveTab(windowHandle);
93+
}
94+
95+
ctrl.Dispose();
96+
}
97+
}
98+
})
99+
.Build();
60100

61101
browser.LoadingStateChanged += OnBrowserLoadingStateChanged;
62102
browser.ConsoleMessage += OnBrowserConsoleMessage;
@@ -480,16 +520,14 @@ public void ShowDevToolsDocked()
480520
}
481521

482522
//Find devToolsControl in Controls collection
483-
DevToolsContainerControl devToolsControl = null;
484-
devToolsControl = browserSplitContainer.Panel2.Controls.Find(nameof(devToolsControl), false).FirstOrDefault() as DevToolsContainerControl;
523+
Control devToolsControl = null;
524+
devToolsControl = browserSplitContainer.Panel2.Controls.Find(nameof(devToolsControl), false).FirstOrDefault();
485525

486526
if (devToolsControl == null || devToolsControl.IsDisposed)
487527
{
488-
devToolsControl = new DevToolsContainerControl()
489-
{
490-
Name = nameof(devToolsControl),
491-
Dock = DockStyle.Fill
492-
};
528+
devToolsControl = Browser.ShowDevToolsDocked(
529+
parentControl: browserSplitContainer.Panel2,
530+
controlName: nameof(devToolsControl));
493531

494532
EventHandler devToolsPanelDisposedHandler = null;
495533
devToolsPanelDisposedHandler = (s, e) =>
@@ -501,27 +539,7 @@ public void ShowDevToolsDocked()
501539

502540
//Subscribe for devToolsPanel dispose event
503541
devToolsControl.Disposed += devToolsPanelDisposedHandler;
504-
505-
//Add new devToolsPanel instance to Controls collection
506-
browserSplitContainer.Panel2.Controls.Add(devToolsControl);
507542
}
508-
509-
if (!devToolsControl.IsHandleCreated)
510-
{
511-
//It's very important the handle for the control is created prior to calling
512-
//SetAsChild, if the handle hasn't been created then manually call CreateControl();
513-
//This code is not required for this example, it's left here for demo purposes.
514-
devToolsControl.CreateControl();
515-
}
516-
517-
//Devtools will be a child of the DevToolsContainerControl
518-
//DevToolsContainerControl is a simple custom Control that's only required
519-
//when CefSettings.MultiThreadedMessageLoop = false so arrow/tab key presses
520-
//are forwarded to DevTools correctly.
521-
var rect = devToolsControl.ClientRectangle;
522-
var windowInfo = new WindowInfo();
523-
windowInfo.SetAsChild(devToolsControl.Handle, rect.Left, rect.Top, rect.Right, rect.Bottom);
524-
Browser.GetBrowserHost().ShowDevTools(windowInfo);
525543
}
526544

527545
public Task<bool> CheckIfDevToolsIsOpenAsync()

CefSharp.WinForms.Example/CefSharp.WinForms.Example.csproj

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,14 @@
8484
<Compile Include="BrowserTabUserControl.Designer.cs">
8585
<DependentUpon>BrowserTabUserControl.cs</DependentUpon>
8686
</Compile>
87-
<Compile Include="ChromiumContainerControl.cs">
88-
<SubType>Component</SubType>
89-
</Compile>
9087
<Compile Include="ControlExtensions.cs" />
9188
<Compile Include="Handlers\DisplayHandler.cs" />
9289
<Compile Include="Handlers\KeyboardHandler.cs" />
93-
<Compile Include="Handlers\LifeSpanHandler.cs" />
9490
<Compile Include="Handlers\MenuHandler.cs" />
9591
<Compile Include="Handlers\MultiFormFocusHandler.cs" />
9692
<Compile Include="Handlers\ScheduleMessagePumpBrowserProcessHandler.cs" />
9793
<Compile Include="Handlers\WinFormsBrowserProcessHandler.cs" />
9894
<Compile Include="Handlers\WinFormsRequestHandler.cs" />
99-
<Compile Include="Helper\PopupAsChildHelper.cs" />
10095
<Compile Include="InputBox.cs">
10196
<SubType>Form</SubType>
10297
</Compile>

CefSharp.WinForms.Example/ChromiumContainerControl.cs

Lines changed: 0 additions & 39 deletions
This file was deleted.

CefSharp.WinForms.Example/Handlers/LifeSpanHandler.cs

Lines changed: 0 additions & 152 deletions
This file was deleted.

0 commit comments

Comments
 (0)