/// <inheritdoc/> /// <remarks> /// NOTE: DevTools popups DO NOT trigger OnBeforePopup. /// </remarks> protected override bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser) { newBrowser = null; //No action so we'll go with the default behaviour. if (onPopupCreated == null) { return(false); } var webBrowser = (ChromiumWebBrowser)chromiumWebBrowser; //We need to execute sync here so IWindowInfo.SetAsChild is called before we return false; webBrowser.InvokeSyncOnUiThreadIfRequired(new Action(() => { var control = new ChromiumHostControl { Dock = DockStyle.Fill }; control.CreateControl(); onPopupCreated?.Invoke(control, targetUrl); var rect = control.ClientRectangle; windowInfo.SetAsChild(control.Handle, rect.Left, rect.Top, rect.Right, rect.Bottom); })); return(false); }
/// <inheritdoc/> protected override bool DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser) { if (browser.IsPopup) { var control = ChromiumHostControl.FromBrowser(browser); //We don't have a parent control so we allow the default behaviour, required to close //default popups e.g. DevTools if (control == null) { return(false); } //If the main browser is disposed or the handle has been released then we don't //need to remove the popup (likely removed from menu) if (!control.IsDisposed && control.IsHandleCreated) { //We need to invoke in a sync fashion so our IBrowser object is still in scope //Calling in an async fashion leads to the IBrowser being disposed before we //can access it. control.InvokeSyncOnUiThreadIfRequired(new Action(() => { onPopupDestroyed?.Invoke(control, browser); })); } } //No WM_CLOSE message will be sent, manually handle closing return(true); }
/// <summary> /// Open DevTools using your own Control as the parent. If inspectElementAtX and/or inspectElementAtY are specified then /// the element at the specified (x,y) location will be inspected. /// For resize/moving to work correctly you will need to use the <see cref="CefSharp.WinForms.Handler.LifeSpanHandler"/> implementation. /// (Set <see cref="ChromiumWebBrowser.LifeSpanHandler"/> to an instance of <see cref="CefSharp.WinForms.Handler.LifeSpanHandler"/>) /// </summary> /// <param name="chromiumWebBrowser"><see cref="ChromiumWebBrowser"/> instance</param> /// <param name="addParentControl"> /// Action that is Invoked when the DevTools Host Control has been created and needs to be added to it's parent. /// It's important the control is added to it's intended parent at this point so the <see cref="Control.ClientRectangle"/> /// can be calculated to set the initial display size.</param> /// <param name="inspectElementAtX">x coordinate (used for inspectElement)</param> /// <param name="inspectElementAtY">y coordinate (used for inspectElement)</param> /// <returns>Returns the <see cref="Control"/> that hosts the DevTools instance if successful, otherwise returns null on error.</returns> public static Control ShowDevToolsDocked(this IChromiumWebBrowserBase chromiumWebBrowser, Action <ChromiumHostControl> addParentControl, string controlName = nameof(ChromiumHostControl) + "DevTools", DockStyle dockStyle = DockStyle.Fill, int inspectElementAtX = 0, int inspectElementAtY = 0) { if (chromiumWebBrowser.IsDisposed || addParentControl == null) { return(null); } var host = chromiumWebBrowser.GetBrowserHost(); if (host == null) { return(null); } var control = new ChromiumHostControl() { Name = controlName, Dock = dockStyle }; control.CreateControl(); //It's now time for the user to add the control to it's parent addParentControl(control); //Devtools will be a child of the ChromiumHostControl var rect = control.ClientRectangle; var windowInfo = new WindowInfo(); var windowBounds = new CefSharp.Structs.Rect(rect.X, rect.Y, rect.Width, rect.Height); windowInfo.SetAsChild(control.Handle, windowBounds); host.ShowDevTools(windowInfo, inspectElementAtX, inspectElementAtY); return(control); }
/// <summary> /// Initializes a new instance of the <see cref="ParentFormMessageInterceptor"/> class. /// </summary> /// <param name="browser">The browser.</param> public ParentFormMessageInterceptor(ChromiumHostControl browser) { Browser = browser; // Get notified if our browser window parent changes: Browser.ParentChanged += ParentParentChanged; // Find the browser form to subclass to monitor WM_MOVE/WM_MOVING RefindParentForm(); }
/// <inheritdoc /> protected override void OnLoadingStateChange(IWebBrowser chromiumWebBrowser, LoadingStateChangedEventArgs args) { var browser = args.Browser; if (browser.IsPopup) { var control = ChromiumHostControl.FromBrowser(browser); control?.OnLoadingStateChange(args); } base.OnLoadingStateChange(chromiumWebBrowser, args); }
/// <inheritdoc /> protected override void OnFrameLoadStart(IWebBrowser chromiumWebBrowser, FrameLoadStartEventArgs args) { var browser = args.Browser; if (browser.IsPopup) { var control = ChromiumHostControl.FromBrowser(browser); control?.OnFrameLoadStart(args); } base.OnFrameLoadStart(chromiumWebBrowser, args); }
/// <inheritdoc /> protected override void OnStatusMessage(IWebBrowser chromiumWebBrowser, StatusMessageEventArgs args) { var browser = args.Browser; if (browser.IsPopup) { var control = ChromiumHostControl.FromBrowser(browser); control?.OnStatusMessage(args); } base.OnStatusMessage(chromiumWebBrowser, args); }
/// <inheritdoc /> protected override bool OnConsoleMessage(IWebBrowser chromiumWebBrowser, ConsoleMessageEventArgs args) { var browser = args.Browser; if (browser.IsPopup) { var control = ChromiumHostControl.FromBrowser(browser); control?.OnConsoleMessage(args); } return(base.OnConsoleMessage(chromiumWebBrowser, args)); }
/// <inheritdoc /> protected override void OnAddressChanged(IWebBrowser chromiumWebBrowser, AddressChangedEventArgs args) { var browser = args.Browser; if (browser.IsPopup) { var control = ChromiumHostControl.FromBrowser(browser); control?.OnAddressChanged(args); } base.OnAddressChanged(chromiumWebBrowser, args); }
public void RemoveTab(ChromiumHostControl ctrl) { if (!ctrl.IsDisposed) { var tabPage = ctrl.GetParentOfType <TabPage>(); if (tabPage == null) { throw new Exception("Unable to find parent TabPage"); } browserTabControl.TabPages.Remove(tabPage); } }
public BrowserTabUserControl(ChromiumHostControl chromiumHostControl) { InitializeComponent(); Browser = chromiumHostControl; browserPanel.Controls.Add(chromiumHostControl); chromiumHostControl.LoadingStateChanged += OnBrowserLoadingStateChanged; chromiumHostControl.ConsoleMessage += OnBrowserConsoleMessage; chromiumHostControl.TitleChanged += OnBrowserTitleChanged; chromiumHostControl.AddressChanged += OnBrowserAddressChanged; chromiumHostControl.StatusMessage += OnBrowserStatusMessage; chromiumHostControl.IsBrowserInitializedChanged += OnIsBrowserInitializedChanged; chromiumHostControl.LoadError += OnLoadError; }
/// <inheritdoc/> protected override void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser) { if (browser.IsPopup) { //WinForms will kindly lookup the child control from it's handle //If no parentControl then likely it's a native popup created by CEF //(Devtools by default will open as a popup, at this point the Url hasn't been set, so // we're going with this assumption as it fits the use case currently) var control = ChromiumHostControl.FromBrowser(browser); //If control is null then we'll treat as a native popup (do nothing) //If control is disposed there's nothing for us to do either. if (control != null && !control.IsDisposed) { control.BrowserHwnd = browser.GetHost().GetWindowHandle(); control.InvokeOnUiThreadIfRequired(() => { var interceptor = new ParentFormMessageInterceptor(control); interceptor.Moving += (sender, args) => { if (!browser.IsDisposed) { browser?.GetHost()?.NotifyMoveOrResizeStarted(); } }; popupParentFormMessageInterceptors.Add(browser.Identifier, interceptor); }); control.BrowserCore = browser; control.RaiseIsBrowserInitializedChangedEvent(); } onPopupBrowserCreated?.Invoke(control, browser); } }
/// <summary> /// Used to add a Popup browser as a Tab /// </summary> /// <param name="browserHostControl"></param> public void AddTab(ChromiumHostControl browserHostControl, string url) { browserTabControl.SuspendLayout(); var browser = new BrowserTabUserControl(browserHostControl) { Dock = DockStyle.Fill, Bounds = browserTabControl.Bounds }; var tabPage = new TabPage(url) { Dock = DockStyle.Fill }; tabPage.Controls.Add(browser); browserTabControl.TabPages.Add(tabPage); //Make newly created tab active browserTabControl.SelectedTab = tabPage; browserTabControl.ResumeLayout(true); }
/// <inheritdoc/> /// <remarks> /// NOTE: DevTools popups DO NOT trigger OnBeforePopup. /// </remarks> protected override bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser) { newBrowser = null; PopupCreation userAction = onBeforePopupCreated?.Invoke(chromiumWebBrowser, browser, frame, targetUrl, targetFrameName, targetDisposition, userGesture, browserSettings) ?? PopupCreation.Continue; //Cancel popup creation if (userAction == PopupCreation.Cancel) { return(true); } if (userAction == PopupCreation.ContinueWithJavascriptDisabled) { noJavascriptAccess = true; } //No action so we'll go with the default behaviour. if (onPopupCreated == null) { return(false); } var webBrowser = (ChromiumWebBrowser)chromiumWebBrowser; //Load and Display Handlers are used to trigger the relevant events. //If they are already assigned we'll leave the user preference in place if (webBrowser.LoadHandler == null) { webBrowser.LoadHandler = new LoadHandler(); } if (webBrowser.DisplayHandler == null) { webBrowser.DisplayHandler = new DisplayHandler(); } //We need to execute sync here so IWindowInfo.SetAsChild is called before we return false; webBrowser.InvokeSyncOnUiThreadIfRequired(new Action(() => { ChromiumHostControl control = chromiumHostControlCreatedDelegate?.Invoke(); if (control == null) { control = new ChromiumHostControl { Dock = DockStyle.Fill }; } control.CreateControl(); onPopupCreated?.Invoke(control, targetUrl); var rect = control.ClientRectangle; var windowBounds = new CefSharp.Structs.Rect(rect.X, rect.Y, rect.Width, rect.Height); windowInfo.SetAsChild(control.Handle, windowBounds); })); return(false); }