2019-12-09 20:04:46 +10:00
// Copyright © 2019 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
using System ;
2021-06-04 14:51:49 +10:00
using System.Windows.Forms ;
using CefSharp.WinForms.Host ;
2019-12-09 20:04:46 +10:00
namespace CefSharp.WinForms
{
/// <summary>
/// Helper extensions for performing common CefSharp related WinForms tasks
/// </summary>
2019-12-10 08:09:22 +10:00
public static class WebBrowserExtensions
2019-12-09 20:04:46 +10:00
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool DestroyWindow ( IntPtr hWnd ) ;
/// <summary>
/// Manually call https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-destroywindow
/// passing in the handle returned from <see cref="IBrowserHost.GetWindowHandle"/>.
/// This method can be used to manually close the underlying CefBrowser instance.
/// This will avoid the WM_Close message that CEF sends by default to the top level window.
/// (Which closes your application). This method should generally only be used in the WinForms version.
/// </summary>
2022-01-10 10:00:46 +10:00
/// <param name="chromiumWebBrowser">the <see cref="ChromiumWebBrowser"/> or <see cref="ChromiumHostControl"/> instance.</param>
2019-12-09 20:04:46 +10:00
/// <returns>If the function succeeds, the return value is true.</returns>
/// <example>
/// <code>
/// //Invoke on the CEF UI Thread
/// Cef.UIThreadTaskFactory.StartNew(() =>
/// {
/// var closed = chromiumWebBrowser.DestroyWindow();
/// });
/// </code>
/// </example>
2022-01-10 10:00:46 +10:00
public static bool DestroyWindow ( this IChromiumWebBrowserBase chromiumWebBrowser )
2019-12-09 20:04:46 +10:00
{
if ( ! Cef . CurrentlyOnThread ( CefThreadIds . TID_UI ) )
{
throw new InvalidOperationException ( "This method can only be called on the CEF UI thread." +
"Use Cef.UIThreadTaskFactory to marshal your call onto the CEF UI Thread." ) ;
}
if ( chromiumWebBrowser . IsDisposed )
{
return false ;
}
2022-01-05 10:14:24 +10:00
var browser = chromiumWebBrowser . BrowserCore ;
2019-12-09 20:04:46 +10:00
if ( browser = = null )
{
return false ;
}
var handle = browser . GetHost ( ) . GetWindowHandle ( ) ;
return DestroyWindow ( handle ) ;
}
2021-06-04 14:51:49 +10:00
/// <summary>
/// Open DevTools using <paramref name="parentControl"/> as the parent control. 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="parentControl">Control used as the parent for DevTools (a custom control will be added to the <see cref="Control.Controls"/> collection)</param>
2022-02-01 14:07:01 +10:00
/// <param name="controlName">Control name</param>
/// <param name="dockStyle">Dock Style</param>
2021-06-04 14:51:49 +10:00
/// <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>
2021-11-30 13:46:13 +10:00
public static Control ShowDevToolsDocked ( this IChromiumWebBrowserBase chromiumWebBrowser , Control parentControl , string controlName = nameof ( ChromiumHostControl ) + "DevTools" , DockStyle dockStyle = DockStyle . Fill , int inspectElementAtX = 0 , int inspectElementAtY = 0 )
2021-06-04 14:51:49 +10:00
{
if ( chromiumWebBrowser . IsDisposed | | parentControl = = null | | parentControl . IsDisposed )
{
return null ;
}
return chromiumWebBrowser . ShowDevToolsDocked ( ( ctrl ) = > { parentControl . Controls . Add ( ctrl ) ; } , controlName , dockStyle , inspectElementAtX , inspectElementAtY ) ;
}
/// <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>
2022-02-01 14:07:01 +10:00
/// <param name="controlName">control name</param>
/// <param name="dockStyle">Dock Style</param>
2021-06-04 14:51:49 +10:00
/// <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>
2021-11-30 13:46:13 +10:00
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 )
2021-06-04 14:51:49 +10:00
{
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 ( ) ;
2021-10-22 13:16:45 +10:00
var windowBounds = new CefSharp . Structs . Rect ( rect . X , rect . Y , rect . Width , rect . Height ) ;
windowInfo . SetAsChild ( control . Handle , windowBounds ) ;
2021-06-04 14:51:49 +10:00
host . ShowDevTools ( windowInfo , inspectElementAtX , inspectElementAtY ) ;
return control ;
}
2019-12-09 20:04:46 +10:00
}
}