Skip to content

Commit 6e9e4a9

Browse files
committed
WinForms - ChromiumHostControl add BrowserCore and IsBrowserInitialized event
- Can now access the IBrowser property via ChromiumHostControl.BrowserCore - The ChromiumHostControl.IsBrowserInitialized event will be raised when the underlying CEF browser has been created.
1 parent 129879c commit 6e9e4a9

File tree

4 files changed

+71
-21
lines changed

4 files changed

+71
-21
lines changed

CefSharp.WinForms.Example/BrowserTabUserControl.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,14 @@ public BrowserTabUserControl(Action<string, int?> openNewTab, string url, bool m
9191
}
9292
}
9393
})
94-
.OnPopupBrowserCreated((popupBrowser) =>
94+
.OnPopupBrowserCreated((ctrl, popupBrowser) =>
9595
{
96+
//The host control maybe null if the popup was hosted in a native Window e.g. Devtools by default
97+
if(ctrl == null)
98+
{
99+
return;
100+
}
101+
96102
//You can access all the core browser functionality via IBrowser
97103
//frames, browwser host, etc.
98104
var isPopup = popupBrowser.IsPopup;

CefSharp.WinForms/ChromiumWebBrowser.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,13 +198,6 @@ public IRequestContext RequestContext
198198
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
199199
/// </summary>
200200
public event EventHandler<TitleChangedEventArgs> TitleChanged;
201-
/// <summary>
202-
/// Event called after the underlying CEF browser instance has been created.
203-
/// It's important to note this event is fired on a CEF UI thread, which by default is not the same as your application UI
204-
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
205-
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
206-
/// </summary>
207-
public event EventHandler IsBrowserInitializedChanged;
208201

209202
/// <summary>
210203
/// A flag that indicates whether the state of the control currently supports the GoForward action (true) or not (false).
@@ -398,7 +391,6 @@ private void InternalDispose(bool disposing)
398391
ConsoleMessage = null;
399392
FrameLoadEnd = null;
400393
FrameLoadStart = null;
401-
IsBrowserInitializedChanged = null;
402394
LoadError = null;
403395
LoadingStateChanged = null;
404396
StatusMessage = null;
@@ -604,6 +596,7 @@ private void CreateBrowser()
604596
/// <param name="browser">The browser.</param>
605597
partial void OnAfterBrowserCreated(IBrowser browser)
606598
{
599+
BrowserCore = browser;
607600
BrowserHwnd = browser.GetHost().GetWindowHandle();
608601

609602
// By the time this callback gets called, this control
@@ -639,7 +632,7 @@ partial void OnAfterBrowserCreated(IBrowser browser)
639632
browser.GetHost()?.SetFocus(true);
640633
}
641634

642-
IsBrowserInitializedChanged?.Invoke(this, EventArgs.Empty);
635+
RaiseIsBrowserInitializedChangedEvent();
643636
}
644637

645638
/// <summary>
@@ -769,7 +762,7 @@ protected override void OnGotFocus(EventArgs e)
769762
/// <summary>
770763
/// Returns the current IBrowser Instance
771764
/// </summary>
772-
/// <returns>browser instance or null</returns>
765+
/// <returns>browser instance</returns>
773766
public IBrowser GetBrowser()
774767
{
775768
ThrowExceptionIfDisposed();

CefSharp.WinForms/Handler/LifeSpanHandler.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ namespace CefSharp.WinForms.Handler
2424
/// Called when the <see cref="IBrowser"/> instance has been created.
2525
/// The <see cref="IBrowser"/> reference will be valid until <see cref="OnPopupDestroyedDelegate"/> is called
2626
/// </summary>
27+
/// <param name="control">popup host control, maybe null if Browser is hosted in a native Popup window.
28+
/// DevTools by default will be hosted in a native popup window.</param>
2729
/// <param name="browser">browser</param>
28-
public delegate void OnPopupBrowserCreatedDelegate(IBrowser browser);
30+
public delegate void OnPopupBrowserCreatedDelegate(ChromiumHostControl control, IBrowser browser);
2931

3032
/// <summary>
3133
/// Called when the <see cref="ChromiumHostControl"/> is to be removed from it's parent.
@@ -53,8 +55,7 @@ protected override bool DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser
5355
{
5456
if (browser.IsPopup)
5557
{
56-
var windowHandle = browser.GetHost().GetWindowHandle();
57-
var control = Control.FromChildHandle(windowHandle) as ChromiumHostControl;
58+
var control = ChromiumHostControl.FromBrowser(browser);
5859

5960
//We don't have a parent control so we allow the default behaviour, required to close
6061
//default popups e.g. DevTools
@@ -86,21 +87,17 @@ protected override void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser
8687
{
8788
if (browser.IsPopup)
8889
{
89-
onPopupBrowserCreated?.Invoke(browser);
90-
91-
var windowHandle = browser.GetHost().GetWindowHandle();
92-
9390
//WinForms will kindly lookup the child control from it's handle
9491
//If no parentControl then likely it's a native popup created by CEF
9592
//(Devtools by default will open as a popup, at this point the Url hasn't been set, so
9693
// we're going with this assumption as it fits the use case currently)
97-
var control = Control.FromChildHandle(windowHandle) as ChromiumHostControl;
94+
var control = ChromiumHostControl.FromBrowser(browser);
9895

9996
//If control is null then we'll treat as a native popup (do nothing)
10097
//If control is disposed there's nothing for us to do either.
10198
if (control != null && !control.IsDisposed)
10299
{
103-
control.BrowserHwnd = windowHandle;
100+
control.BrowserHwnd = browser.GetHost().GetWindowHandle();
104101

105102
control.InvokeOnUiThreadIfRequired(() =>
106103
{
@@ -114,8 +111,13 @@ protected override void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser
114111
};
115112

116113
popupParentFormMessageInterceptors.Add(browser.Identifier, interceptor);
117-
});
114+
});
115+
116+
control.BrowserCore = browser;
117+
control.RaiseIsBrowserInitializedChangedEvent();
118118
}
119+
120+
onPopupBrowserCreated?.Invoke(control, browser);
119121
}
120122
}
121123

CefSharp.WinForms/Host/ChromiumHostControl.cs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ namespace CefSharp.WinForms.Host
1919
Designer(typeof(ChromiumWebBrowserDesigner))]
2020
public class ChromiumHostControl : Control
2121
{
22+
/// <summary>
23+
/// Get access to the core <see cref="IBrowser"/> instance.
24+
/// Maybe null if the underlying CEF Browser has not yet been
25+
/// created or if this control has been disposed.
26+
/// </summary>
27+
public IBrowser BrowserCore { get; internal set; }
2228
/// <summary>
2329
/// IntPtr that represents the CefBrowser Hwnd
2430
/// Used for sending messages to the browser
@@ -33,6 +39,14 @@ public class ChromiumHostControl : Control
3339
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
3440
public bool IsActivating { get; set; }
3541

42+
/// <summary>
43+
/// Event called after the underlying CEF browser instance has been created.
44+
/// It's important to note this event is fired on a CEF UI thread, which by default is not the same as your application UI
45+
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
46+
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
47+
/// </summary>
48+
public event EventHandler IsBrowserInitializedChanged;
49+
3650
/// <summary>
3751
/// Gets the default size of the control.
3852
/// </summary>
@@ -161,10 +175,45 @@ protected override void Dispose(bool disposing)
161175
{
162176
if (disposing)
163177
{
178+
BrowserCore = null;
164179
BrowserHwnd = IntPtr.Zero;
180+
IsBrowserInitializedChanged = null;
165181
}
166182

167183
base.Dispose(disposing);
168184
}
185+
186+
/// <summary>
187+
/// Trigger the <see cref="IsBrowserInitializedChanged"/> event
188+
/// </summary>
189+
internal void RaiseIsBrowserInitializedChangedEvent()
190+
{
191+
IsBrowserInitializedChanged?.Invoke(this, EventArgs.Empty);
192+
}
193+
194+
/// <summary>
195+
/// Gets the <see cref="ChromiumHostControl"/> associated with
196+
/// a specific <see cref="IBrowser"/> instance.
197+
/// </summary>
198+
/// <param name="browser">browser</param>
199+
/// <returns>returns the assocaited <see cref="ChromiumHostControl"/> or null if Disposed or no host found.</returns>
200+
public static ChromiumHostControl FromBrowser(IBrowser browser)
201+
{
202+
if(browser.IsDisposed)
203+
{
204+
return null;
205+
}
206+
207+
var windowHandle = browser.GetHost().GetWindowHandle();
208+
209+
if(windowHandle == IntPtr.Zero)
210+
{
211+
return null;
212+
}
213+
214+
var control = Control.FromChildHandle(windowHandle) as ChromiumHostControl;
215+
216+
return control;
217+
}
169218
}
170219
}

0 commit comments

Comments
 (0)