Skip to content

Commit

Permalink
WinForms - Add LifeSpanHandler implementation capable of hosting popu…
Browse files Browse the repository at this point in the history
…ps 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
  • Loading branch information
amaitland authored Jun 4, 2021
1 parent 2371370 commit 3dc37b2
Show file tree
Hide file tree
Showing 13 changed files with 589 additions and 617 deletions.
80 changes: 49 additions & 31 deletions CefSharp.WinForms.Example/BrowserTabUserControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using CefSharp.Example.JavascriptBinding;
using CefSharp.WinForms.Example.Handlers;
using CefSharp.WinForms.Experimental;
using CefSharp.WinForms.Handler;

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

//Handling DevTools docked inside the same window requires
//an instance of the LifeSpanHandler all the window events,
//e.g. creation, resize, moving, closing etc.
browser.LifeSpanHandler = new LifeSpanHandler(openPopupsAsTabs: false);
//The CefSharp.WinForms.Handler.LifeSpanHandler implementation
//allows for Popups to be hosted in Controls/Tabs
//This example also demonstrates docking DevTools in a SplitPanel
browser.LifeSpanHandler = LifeSpanHandler
.Create()
.OnPopupCreated((ctrl, targetUrl) =>
{
//Don't try using ctrl.FindForm() here as
//the control hasn't been attached to a parent yet.
if (FindForm() is BrowserForm owner)
{
owner.AddTab(ctrl, targetUrl);
}
})
.OnPopupDestroyed((ctrl, popupBrowser) =>
{
//If we docked DevTools (hosted it ourselves rather than the default popup)
//Used when the BrowserTabUserControl.ShowDevToolsDocked method is called
if (popupBrowser.MainFrame.Url.Equals("devtools://devtools/devtools_app.html"))
{
//Dispose of the parent control we used to host DevTools, this will release the DevTools window handle
//and the ILifeSpanHandler.OnBeforeClose() will be call after.
ctrl.Dispose();
}
else
{
//If browser is disposed or the handle has been released then we don't
//need to remove the tab in this example. The user likely used the
// File -> Close Tab menu option which also calls BrowserForm.RemoveTab
if (!ctrl.IsDisposed && ctrl.IsHandleCreated)
{
if (ctrl.FindForm() is BrowserForm owner)
{
var windowHandle = popupBrowser.GetHost().GetWindowHandle();

owner.RemoveTab(windowHandle);
}

ctrl.Dispose();
}
}
})
.Build();

browser.LoadingStateChanged += OnBrowserLoadingStateChanged;
browser.ConsoleMessage += OnBrowserConsoleMessage;
Expand Down Expand Up @@ -480,16 +520,14 @@ public void ShowDevToolsDocked()
}

//Find devToolsControl in Controls collection
DevToolsContainerControl devToolsControl = null;
devToolsControl = browserSplitContainer.Panel2.Controls.Find(nameof(devToolsControl), false).FirstOrDefault() as DevToolsContainerControl;
Control devToolsControl = null;
devToolsControl = browserSplitContainer.Panel2.Controls.Find(nameof(devToolsControl), false).FirstOrDefault();

if (devToolsControl == null || devToolsControl.IsDisposed)
{
devToolsControl = new DevToolsContainerControl()
{
Name = nameof(devToolsControl),
Dock = DockStyle.Fill
};
devToolsControl = Browser.ShowDevToolsDocked(
parentControl: browserSplitContainer.Panel2,
controlName: nameof(devToolsControl));

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

//Subscribe for devToolsPanel dispose event
devToolsControl.Disposed += devToolsPanelDisposedHandler;

//Add new devToolsPanel instance to Controls collection
browserSplitContainer.Panel2.Controls.Add(devToolsControl);
}

if (!devToolsControl.IsHandleCreated)
{
//It's very important the handle for the control is created prior to calling
//SetAsChild, if the handle hasn't been created then manually call CreateControl();
//This code is not required for this example, it's left here for demo purposes.
devToolsControl.CreateControl();
}

//Devtools will be a child of the DevToolsContainerControl
//DevToolsContainerControl is a simple custom Control that's only required
//when CefSettings.MultiThreadedMessageLoop = false so arrow/tab key presses
//are forwarded to DevTools correctly.
var rect = devToolsControl.ClientRectangle;
var windowInfo = new WindowInfo();
windowInfo.SetAsChild(devToolsControl.Handle, rect.Left, rect.Top, rect.Right, rect.Bottom);
Browser.GetBrowserHost().ShowDevTools(windowInfo);
}

public Task<bool> CheckIfDevToolsIsOpenAsync()
Expand Down
5 changes: 0 additions & 5 deletions CefSharp.WinForms.Example/CefSharp.WinForms.Example.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,14 @@
<Compile Include="BrowserTabUserControl.Designer.cs">
<DependentUpon>BrowserTabUserControl.cs</DependentUpon>
</Compile>
<Compile Include="ChromiumContainerControl.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ControlExtensions.cs" />
<Compile Include="Handlers\DisplayHandler.cs" />
<Compile Include="Handlers\KeyboardHandler.cs" />
<Compile Include="Handlers\LifeSpanHandler.cs" />
<Compile Include="Handlers\MenuHandler.cs" />
<Compile Include="Handlers\MultiFormFocusHandler.cs" />
<Compile Include="Handlers\ScheduleMessagePumpBrowserProcessHandler.cs" />
<Compile Include="Handlers\WinFormsBrowserProcessHandler.cs" />
<Compile Include="Handlers\WinFormsRequestHandler.cs" />
<Compile Include="Helper\PopupAsChildHelper.cs" />
<Compile Include="InputBox.cs">
<SubType>Form</SubType>
</Compile>
Expand Down
39 changes: 0 additions & 39 deletions CefSharp.WinForms.Example/ChromiumContainerControl.cs

This file was deleted.

152 changes: 0 additions & 152 deletions CefSharp.WinForms.Example/Handlers/LifeSpanHandler.cs

This file was deleted.

Loading

0 comments on commit 3dc37b2

Please sign in to comment.