Update
Updated cefsharp and removed flash. But there is now a bug where the browser crashed when trying to download anything.
This commit is contained in:
parent
d685e803b3
commit
81286909c6
776 changed files with 255315 additions and 42 deletions
BIN
packages/CefSharp.WinForms.113.1.40/.signature.p7s
vendored
Normal file
BIN
packages/CefSharp.WinForms.113.1.40/.signature.p7s
vendored
Normal file
Binary file not shown.
BIN
packages/CefSharp.WinForms.113.1.40/CefSharp.WinForms.113.1.40.nupkg
vendored
Normal file
BIN
packages/CefSharp.WinForms.113.1.40/CefSharp.WinForms.113.1.40.nupkg
vendored
Normal file
Binary file not shown.
62
packages/CefSharp.WinForms.113.1.40/Readme.txt
vendored
Normal file
62
packages/CefSharp.WinForms.113.1.40/Readme.txt
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
CefSharp Nuget Package
|
||||
|
||||
Background:
|
||||
CefSharp is a .Net wrapping library for CEF (Chromium Embedded Framework) https://bitbucket.org/chromiumembedded/cef
|
||||
CEF is a C/C++ library that allows developers to embed the HTML content rendering strengths of Google's Chrome open source WebKit engine (Chromium).
|
||||
|
||||
Post Installation:
|
||||
- Add an app.manifest to your exe if you don't already have one, it's required for Windows 10 compatability, GPU detection, HighDPI support and tooltips. The https://github.com/cefsharp/CefSharp.MinimalExample project contains an example app.manifest file in the root of the WPF/WinForms/OffScreen examples.
|
||||
- For `x86` or x64` set your projects PlatformTarget architecture to `x86` or `x64`.
|
||||
- `AnyCPU` target is supported though requires additional code/changes see https://github.com/cefsharp/CefSharp/issues/1714 for details.
|
||||
- Read the release notes for your version https://github.com/cefsharp/CefSharp/releases (Any known issues will be listed here)
|
||||
- Read the `Need to know/limitations` section of the General usage guide (https://github.com/cefsharp/CefSharp/wiki/General-Usage#need-to-knowlimitations)
|
||||
- Check your output `\bin` directory to make sure the appropriate references have been copied.
|
||||
|
||||
Deployment:
|
||||
- Make sure a minimum of `Visual C++ 2019` is installed (`x86` or x64` depending on your build) or package the runtime dlls with your application, see the FAQ for details.
|
||||
|
||||
What's New:
|
||||
See https://github.com/cefsharp/CefSharp/releases
|
||||
IMPORTANT NOTE - Visual C++ 2019 or greater is required
|
||||
IMPORTANT NOTE - .NET Framework 4.5.2 or greater is required.
|
||||
IMPORTANT NOTE - Chromium support for Windows 7/8/8.1 ends with version 109, starting with version 110 a minimum of Windows 10 is required.
|
||||
|
||||
Basic Troubleshooting:
|
||||
- Minimum of .Net 4.5.2
|
||||
- Minimum of `Visual C++ 2019 Redist` is installed (either `x86` or `x64` depending on your application).
|
||||
- Please ensure your binaries directory contains these required dependencies:
|
||||
* libcef.dll (Chromium Embedded Framework Core library)
|
||||
* icudtl.dat (Unicode Support data)
|
||||
* chrome_elf.dll(Crash reporting library)
|
||||
* snapshot_blob.bin, v8_context_snapshot.bin (V8 snapshot data)
|
||||
* locales\en-US.pak, chrome_100_percent.pak, chrome_200_percent.pak, resources.pak, d3dcompiler_47.dll, libEGL.dll, libGLESv2.dll
|
||||
- Whilst these are technically listed as optional, the browser is unlikely to function without these files.
|
||||
- See https://github.com/cefsharp/CefSharp/wiki/Output-files-description-table-%28Redistribution%29 for details
|
||||
* CefSharp.Core.dll, CefSharp.dll, CefSharp.Core.Runtime.dll
|
||||
CefSharp.BrowserSubprocess.exe, CefSharp.BrowserSubProcess.Core.dll
|
||||
- These are required CefSharp binaries that are the common core logic binaries of CefSharp.
|
||||
* One of the following UI presentation libraries:
|
||||
* CefSharp.WinForms.dll
|
||||
* CefSharp.Wpf.dll
|
||||
* CefSharp.OffScreen.dll
|
||||
- Additional CEF files are described at: https://github.com/cefsharp/CefSharp/wiki/Output-files-description-table-%28Redistribution%29
|
||||
- NOTE: CefSharp does not currently support CEF sandboxing.
|
||||
- By default `CEF` has it's own log file, `Debug.log` which is located in your executing folder. e.g. `bin`
|
||||
|
||||
For further help please read the following content:
|
||||
- Quick Start https://github.com/cefsharp/CefSharp/wiki/Quick-Start
|
||||
- General Usage Guide https://github.com/cefsharp/CefSharp/wiki/General-Usage
|
||||
- Minimal Example Projects showing the browser in action (https://github.com/cefsharp/CefSharp.MinimalExample)
|
||||
- CefSharp GitHub https://github.com/cefsharp/CefSharp
|
||||
- CefSharp's Wiki on github (https://github.com/cefsharp/CefSharp/wiki)
|
||||
- FAQ: https://github.com/cefsharp/CefSharp/wiki/Frequently-asked-questions
|
||||
- Troubleshooting guide (https://github.com/cefsharp/CefSharp/wiki/Trouble-Shooting)
|
||||
- CefSharp vs Cef (https://github.com/cefsharp/CefSharp/blob/master/CONTRIBUTING.md#cefsharp-vs-cef)
|
||||
- Got a question? Ask it on GitHub Discussions (https://github.com/cefsharp/CefSharp/discussions)
|
||||
- If you have a reproducible bug then please open an issue on `GitHub` making sure to complete the bug report template.
|
||||
|
||||
Please consider giving back, it's only with your help will this project to continue.
|
||||
Sponsor the project via GitHub sponsors (https://github.com/sponsors/amaitland)
|
||||
|
||||
Regards,
|
||||
Alex Maitland
|
1639
packages/CefSharp.WinForms.113.1.40/lib/net452/CefSharp.WinForms.XML
vendored
Normal file
1639
packages/CefSharp.WinForms.113.1.40/lib/net452/CefSharp.WinForms.XML
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/CefSharp.WinForms.113.1.40/lib/net452/CefSharp.WinForms.dll
vendored
Normal file
BIN
packages/CefSharp.WinForms.113.1.40/lib/net452/CefSharp.WinForms.dll
vendored
Normal file
Binary file not shown.
BIN
packages/CefSharp.WinForms.113.1.40/lib/net452/CefSharp.WinForms.pdb
vendored
Normal file
BIN
packages/CefSharp.WinForms.113.1.40/lib/net452/CefSharp.WinForms.pdb
vendored
Normal file
Binary file not shown.
1639
packages/CefSharp.WinForms.113.1.40/lib/net462/CefSharp.WinForms.XML
vendored
Normal file
1639
packages/CefSharp.WinForms.113.1.40/lib/net462/CefSharp.WinForms.XML
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/CefSharp.WinForms.113.1.40/lib/net462/CefSharp.WinForms.dll
vendored
Normal file
BIN
packages/CefSharp.WinForms.113.1.40/lib/net462/CefSharp.WinForms.dll
vendored
Normal file
Binary file not shown.
BIN
packages/CefSharp.WinForms.113.1.40/lib/net462/CefSharp.WinForms.pdb
vendored
Normal file
BIN
packages/CefSharp.WinForms.113.1.40/lib/net462/CefSharp.WinForms.pdb
vendored
Normal file
Binary file not shown.
14
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/CefSettings.cs
vendored
Normal file
14
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/CefSettings.cs
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright © 2013 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.
|
||||
|
||||
namespace CefSharp.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialization settings. Many of these and other settings can also configured
|
||||
/// using command-line switches.
|
||||
/// </summary>
|
||||
public class CefSettings : CefSettingsBase
|
||||
{
|
||||
}
|
||||
}
|
934
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/ChromiumWebBrowser.cs
vendored
Normal file
934
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/ChromiumWebBrowser.cs
vendored
Normal file
|
@ -0,0 +1,934 @@
|
|||
// Copyright © 2013 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;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using CefSharp.Internals;
|
||||
using CefSharp.Web;
|
||||
using CefSharp.WinForms.Internals;
|
||||
using CefSharp.WinForms.Host;
|
||||
using CefSharp.DevTools.Page;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CefSharp.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// ChromiumWebBrowser is the WinForms web browser control
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Windows.Forms.Control" />
|
||||
/// <seealso cref="CefSharp.WinForms.IWinFormsWebBrowser" />
|
||||
[Docking(DockingBehavior.AutoDock), DefaultEvent("LoadingStateChanged"), ToolboxBitmap(typeof(ChromiumWebBrowser)),
|
||||
Description("CefSharp ChromiumWebBrowser - Chromium Embedded Framework .Net wrapper. https://github.com/cefsharp/CefSharp"),
|
||||
Designer(typeof(ChromiumWebBrowserDesigner))]
|
||||
public partial class ChromiumWebBrowser : ChromiumHostControlBase, IWebBrowserInternal, IWinFormsWebBrowser
|
||||
{
|
||||
//TODO: If we start adding more consts then extract them into a common class
|
||||
//Possibly in the CefSharp assembly and move the WPF ones into there as well.
|
||||
private const uint WS_EX_NOACTIVATE = 0x08000000;
|
||||
|
||||
/// <summary>
|
||||
/// The managed cef browser adapter
|
||||
/// </summary>
|
||||
private IBrowserAdapter managedCefBrowserAdapter;
|
||||
/// <summary>
|
||||
/// The parent form message interceptor
|
||||
/// </summary>
|
||||
private ParentFormMessageInterceptor parentFormMessageInterceptor;
|
||||
/// <summary>
|
||||
/// A flag that indicates whether or not the designer is active
|
||||
/// NOTE: DesignMode becomes false by the time we get to the destructor/dispose so it gets stored here
|
||||
/// </summary>
|
||||
private bool designMode;
|
||||
/// <summary>
|
||||
/// A flag that indicates whether or not <see cref="InitializeFieldsAndCefIfRequired"/> has been called.
|
||||
/// </summary>
|
||||
private bool initialized;
|
||||
/// <summary>
|
||||
/// Has the underlying Cef Browser been created (slightly different to initialized in that
|
||||
/// the browser is initialized in an async fashion)
|
||||
/// </summary>
|
||||
private bool browserCreated;
|
||||
/// <summary>
|
||||
/// A flag indicating if the <see cref="Address"/> was used when calling CreateBrowser
|
||||
/// If false and <see cref="Address"/> contains a non empty string Load will be called
|
||||
/// on the main frame
|
||||
/// </summary>
|
||||
private bool initialAddressLoaded;
|
||||
/// <summary>
|
||||
/// If true the the WS_EX_NOACTIVATE style will be removed so that future mouse clicks
|
||||
/// inside the browser correctly activate and focus the window.
|
||||
/// </summary>
|
||||
private bool removeExNoActivateStyle;
|
||||
/// <summary>
|
||||
/// Browser initialization settings
|
||||
/// </summary>
|
||||
private IBrowserSettings browserSettings;
|
||||
/// <summary>
|
||||
/// The request context (we deliberately use a private variable so we can throw an exception if
|
||||
/// user attempts to set after browser created)
|
||||
/// </summary>
|
||||
private IRequestContext requestContext;
|
||||
|
||||
/// <summary>
|
||||
/// Parking control used to temporarily host the CefBrowser instance
|
||||
/// when <see cref="Control.RecreatingHandle"/> is <c>true</c>.
|
||||
/// </summary>
|
||||
private Control parkingControl;
|
||||
/// <summary>
|
||||
/// This flag is set when the browser gets focus before the underlying CEF browser
|
||||
/// has been initialized.
|
||||
/// </summary>
|
||||
private bool initialFocus;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is disposed.
|
||||
/// </summary>
|
||||
/// <value><see langword="true" /> if this instance is disposed; otherwise, <see langword="false" />.</value>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public new bool IsDisposed
|
||||
{
|
||||
get
|
||||
{
|
||||
return Interlocked.CompareExchange(ref disposeSignaled, 1, 1) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the browser settings.
|
||||
/// </summary>
|
||||
/// <value>The browser settings.</value>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(null)]
|
||||
public IBrowserSettings BrowserSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
//We keep a reference to the browserSettings for the case where
|
||||
//the Control Handle is destroyed then Created see https://github.com/cefsharp/CefSharp/issues/2840
|
||||
//As it's not possible to change settings after the browser has been
|
||||
//created, and changing browserSettings then creating a new handle will
|
||||
//give a subtle different user experience if you aren't expecting it we
|
||||
//return null here even though we still have a reference.
|
||||
if (browserCreated)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return browserSettings;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (browserCreated)
|
||||
{
|
||||
throw new Exception("Browser has already been created. BrowserSettings must be " +
|
||||
"set before the underlying CEF browser is created.");
|
||||
}
|
||||
if (value != null && !Core.ObjectFactory.BrowserSetingsType.IsAssignableFrom(value.UnWrap().GetType()))
|
||||
{
|
||||
throw new Exception(string.Format("BrowserSettings can only be of type {0} or null", Core.ObjectFactory.BrowserSetingsType));
|
||||
}
|
||||
browserSettings = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Activates browser upon creation, the default value is false. Prior to version 73
|
||||
/// the default behaviour was to activate browser on creation (Equivalent of setting this property to true).
|
||||
/// To restore this behaviour set this value to true immediately after you create the <see cref="ChromiumWebBrowser"/> instance.
|
||||
/// https://github.com/chromiumembedded/cef/issues/1856
|
||||
/// </summary>
|
||||
public bool ActivateBrowserOnCreation { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the request context.
|
||||
/// </summary>
|
||||
/// <value>The request context.</value>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(null)]
|
||||
public IRequestContext RequestContext
|
||||
{
|
||||
get { return requestContext; }
|
||||
set
|
||||
{
|
||||
if (browserCreated)
|
||||
{
|
||||
throw new Exception("Browser has already been created. RequestContext must be " +
|
||||
"set before the underlying CEF browser is created.");
|
||||
}
|
||||
if (value != null && !Core.ObjectFactory.RequestContextType.IsAssignableFrom(value.UnWrap().GetType()))
|
||||
{
|
||||
throw new Exception(string.Format("RequestContext can only be of type {0} or null", Core.ObjectFactory.RequestContextType));
|
||||
}
|
||||
requestContext = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the control is currently loading one or more web pages (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is loading; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool IsLoading { get; private set; }
|
||||
/// <summary>
|
||||
/// The text that will be displayed as a ToolTip
|
||||
/// </summary>
|
||||
/// <value>The tooltip text.</value>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(null)]
|
||||
public string TooltipText { get; private set; }
|
||||
/// <summary>
|
||||
/// The address (URL) which the browser control is currently displaying.
|
||||
/// Will automatically be updated as the user navigates to another page (e.g. by clicking on a link).
|
||||
/// </summary>
|
||||
/// <value>The address.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(null)]
|
||||
public string Address { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the browser address changed.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler<AddressChangedEventArgs> AddressChanged;
|
||||
/// <summary>
|
||||
/// Occurs when the browser title changed.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler<TitleChangedEventArgs> TitleChanged;
|
||||
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the state of the control currently supports the GoForward action (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance can go forward; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool CanGoForward { get; private set; }
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the state of the control current supports the GoBack action (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance can go back; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool CanGoBack { get; private set; }
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the WebBrowser is initialized (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is browser initialized; otherwise, <c>false</c>.</value>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool IsBrowserInitialized
|
||||
{
|
||||
get { return InternalIsBrowserInitialized(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ParentFormMessageInterceptor hooks the Form handle and forwards
|
||||
/// the move/active messages to the browser, the default is true
|
||||
/// and should only be required when using <see cref="CefSettingsBase.MultiThreadedMessageLoop"/>
|
||||
/// set to true.
|
||||
/// </summary>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(true)]
|
||||
public bool UseParentFormMessageInterceptor { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// By default when <see cref="Control.OnHandleDestroyed(EventArgs)"/> is called
|
||||
/// the underlying Browser Hwnd is only parked (moved to a temp parent)
|
||||
/// when <see cref="Control.RecreatingHandle"/> is <c>true</c>, there are a few other
|
||||
/// cases where parking of the control is desired, you can force parking by setting
|
||||
/// this property to <c>true</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You may wish to set this property to <c>true</c> when using the browser in conjunction
|
||||
/// with https://github.com/dockpanelsuite/dockpanelsuite
|
||||
/// </remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(true)]
|
||||
public bool ParkControlOnHandleDestroyed { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes static members of the <see cref="ChromiumWebBrowser"/> class.
|
||||
/// </summary>
|
||||
static ChromiumWebBrowser()
|
||||
{
|
||||
if (CefSharpSettings.ShutdownOnExit)
|
||||
{
|
||||
Application.ApplicationExit += OnApplicationExit;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:ApplicationExit" /> event.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
|
||||
private static void OnApplicationExit(object sender, EventArgs e)
|
||||
{
|
||||
Cef.Shutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To control how <see cref="Cef.Shutdown"/> is called, this method will
|
||||
/// unsubscribe from <see cref="Application.ApplicationExit"/>,
|
||||
/// </summary>
|
||||
public static void UnregisterShutdownHandler()
|
||||
{
|
||||
Application.ApplicationExit -= OnApplicationExit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <strong>Important!!!</strong>
|
||||
/// This constructor exists as the WinForms designer requires a parameterless constructor, if you are instantiating
|
||||
/// an instance of this class in code then use the <see cref="ChromiumWebBrowser(string, IRequestContext)"/>
|
||||
/// constructor overload instead. Using this constructor in code is unsupported and you may experience <see cref="NullReferenceException"/>'s
|
||||
/// when attempting to access some of the properties immediately after instantiation.
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public ChromiumWebBrowser()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChromiumWebBrowser"/> class.
|
||||
/// **Important** - When using this constructor the <see cref="Control.Dock"/> property
|
||||
/// will default to <see cref="DockStyle.Fill"/>.
|
||||
/// </summary>
|
||||
/// <param name="html">html string to be initially loaded in the browser.</param>
|
||||
/// <param name="requestContext">(Optional) Request context that will be used for this browser instance, if null the Global
|
||||
/// Request Context will be used.</param>
|
||||
public ChromiumWebBrowser(HtmlString html, IRequestContext requestContext = null) : this(html.ToDataUriString(), requestContext)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChromiumWebBrowser"/> class.
|
||||
/// **Important** - When using this constructor the <see cref="Control.Dock"/> property
|
||||
/// will default to <see cref="DockStyle.Fill"/>.
|
||||
/// </summary>
|
||||
/// <param name="address">The address.</param>
|
||||
/// <param name="requestContext">(Optional) Request context that will be used for this browser instance, if null the Global
|
||||
/// Request Context will be used.</param>
|
||||
public ChromiumWebBrowser(string address, IRequestContext requestContext = null)
|
||||
{
|
||||
Dock = DockStyle.Fill;
|
||||
Address = address;
|
||||
RequestContext = requestContext;
|
||||
|
||||
InitializeFieldsAndCefIfRequired();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Required for designer support - this method cannot be inlined as the designer
|
||||
/// will attempt to load libcef.dll and will subsequently throw an exception.
|
||||
/// TODO: Still not happy with this method name, need something better
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void InitializeFieldsAndCefIfRequired()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
if (!Cef.IsInitialized && !Cef.Initialize(new CefSettings()))
|
||||
{
|
||||
throw new InvalidOperationException(CefInitializeFailedErrorMessage);
|
||||
}
|
||||
|
||||
Cef.AddDisposable(this);
|
||||
|
||||
if (FocusHandler == null)
|
||||
{
|
||||
//If the WinForms UI thread and the CEF UI thread are one in the same
|
||||
//then we don't need the FocusHandler, it's only required when using
|
||||
//MultiThreadedMessageLoop (the default)
|
||||
if (!Cef.CurrentlyOnThread(CefThreadIds.TID_UI))
|
||||
{
|
||||
FocusHandler = new DefaultFocusHandler();
|
||||
}
|
||||
}
|
||||
|
||||
if (browserSettings == null)
|
||||
{
|
||||
browserSettings = Core.ObjectFactory.CreateBrowserSettings(autoDispose: true);
|
||||
}
|
||||
|
||||
managedCefBrowserAdapter = ManagedCefBrowserAdapter.Create(this, false);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If not in design mode; Releases unmanaged and - optionally - managed resources for the <see cref="ChromiumWebBrowser"/>
|
||||
/// </summary>
|
||||
/// <param name="disposing"><see langword="true" /> to release both managed and unmanaged resources; <see langword="false" /> to release only unmanaged resources.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
// Attempt to move the disposeSignaled state from 0 to 1. If successful, we can be assured that
|
||||
// this thread is the first thread to do so, and can safely dispose of the object.
|
||||
if (Interlocked.CompareExchange(ref disposeSignaled, 1, 0) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!designMode)
|
||||
{
|
||||
InternalDispose(disposing);
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources for the <see cref="ChromiumWebBrowser"/>
|
||||
/// </summary>
|
||||
/// <param name="disposing"><see langword="true" /> to release both managed and unmanaged resources; <see langword="false" /> to release only unmanaged resources.</param>
|
||||
/// <remarks>
|
||||
/// This method cannot be inlined as the designer will attempt to load libcef.dll and will subsequently throw an exception.
|
||||
/// </remarks>
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void InternalDispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Interlocked.Exchange(ref browserInitialized, 0);
|
||||
CanExecuteJavascriptInMainFrame = false;
|
||||
|
||||
// Don't maintain a reference to event listeners anylonger:
|
||||
AddressChanged = null;
|
||||
ConsoleMessage = null;
|
||||
FrameLoadEnd = null;
|
||||
FrameLoadStart = null;
|
||||
LoadError = null;
|
||||
LoadingStateChanged = null;
|
||||
StatusMessage = null;
|
||||
TitleChanged = null;
|
||||
JavascriptMessageReceived = null;
|
||||
|
||||
// Release reference to handlers, except LifeSpanHandler which is done after Disposing
|
||||
// ManagedCefBrowserAdapter otherwise the ILifeSpanHandler.DoClose will not be invoked.
|
||||
// We also leave FocusHandler and override with a NoFocusHandler implementation as
|
||||
// it so we can block taking Focus (we're dispoing afterall). Issue #3715
|
||||
FreeHandlersExceptLifeSpanAndFocus();
|
||||
|
||||
FocusHandler = new NoFocusHandler();
|
||||
|
||||
browser = null;
|
||||
BrowserCore = null;
|
||||
|
||||
if (parentFormMessageInterceptor != null)
|
||||
{
|
||||
parentFormMessageInterceptor.Dispose();
|
||||
parentFormMessageInterceptor = null;
|
||||
}
|
||||
|
||||
if (managedCefBrowserAdapter != null)
|
||||
{
|
||||
managedCefBrowserAdapter.Dispose();
|
||||
managedCefBrowserAdapter = null;
|
||||
}
|
||||
|
||||
//Dispose of BrowserSettings if we created it, if user created then they're responsible
|
||||
if (browserSettings != null && browserSettings.AutoDispose)
|
||||
{
|
||||
browserSettings.Dispose();
|
||||
}
|
||||
|
||||
browserSettings = null;
|
||||
|
||||
parkingControl?.Dispose();
|
||||
parkingControl = null;
|
||||
|
||||
// LifeSpanHandler is set to null after managedCefBrowserAdapter.Dispose so ILifeSpanHandler.DoClose
|
||||
// is called.
|
||||
LifeSpanHandler = null;
|
||||
}
|
||||
|
||||
Cef.RemoveDisposable(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Load(string url)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var browserCore = BrowserCore;
|
||||
|
||||
//There's a small window here between CreateBrowser
|
||||
//and OnAfterBrowserCreated where the Address prop
|
||||
//will be updated, no MainFrame.LoadUrl call will be made.
|
||||
if (browserCore == null)
|
||||
{
|
||||
Address = url;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(browserCore.IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!browserCore.IsValid)
|
||||
{
|
||||
throw new InvalidOperationException("IBrowser instance is no longer valid. Control.Handle was likely destroyed.");
|
||||
}
|
||||
|
||||
using (var frame = browserCore.MainFrame)
|
||||
{
|
||||
//Only attempt to call load if frame is valid
|
||||
//I've seen so far one case where the MainFrame is invalid.
|
||||
//As yet unable to reproduce
|
||||
if (frame.IsValid)
|
||||
{
|
||||
frame.LoadUrl(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Capture page screenshot.
|
||||
/// </summary>
|
||||
/// <param name="format">Image compression format (defaults to png).</param>
|
||||
/// <param name="quality">Compression quality from range [0..100] (jpeg only).</param>
|
||||
/// <param name="viewPort">Capture the screenshot of a given region only.</param>
|
||||
/// <param name="fromSurface">Capture the screenshot from the surface, rather than the view. Defaults to true.</param>
|
||||
/// <param name="captureBeyondViewport">Capture the screenshot beyond the viewport. Defaults to false.</param>
|
||||
/// <returns>A task that can be awaited to obtain the screenshot as a byte[].</returns>
|
||||
public async Task<byte[]> CaptureScreenshotAsync(CaptureScreenshotFormat format = CaptureScreenshotFormat.Png, int? quality = null, Viewport viewPort = null, bool fromSurface = true, bool captureBeyondViewport = false)
|
||||
{
|
||||
ThrowExceptionIfDisposed();
|
||||
ThrowExceptionIfBrowserNotInitialized();
|
||||
|
||||
if(viewPort != null && viewPort.Scale <= 0)
|
||||
{
|
||||
throw new ArgumentException($"{nameof(viewPort)}.{nameof(viewPort.Scale)} must be greater than 0.");
|
||||
}
|
||||
|
||||
using (var devToolsClient = browser.GetDevToolsClient())
|
||||
{
|
||||
var screenShot = await devToolsClient.Page.CaptureScreenshotAsync(format, quality, viewPort, fromSurface, captureBeyondViewport).ConfigureAwait(continueOnCapturedContext: false);
|
||||
|
||||
return screenShot.Data;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The javascript object repository, one repository per ChromiumWebBrowser instance.
|
||||
/// </summary>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public IJavascriptObjectRepository JavascriptObjectRepository
|
||||
{
|
||||
get
|
||||
{
|
||||
InitializeFieldsAndCefIfRequired();
|
||||
return managedCefBrowserAdapter == null ? null : managedCefBrowserAdapter.JavascriptObjectRepository;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if one of the Ancestors of this control is sited
|
||||
/// and that site in DesignMode.
|
||||
/// </summary>
|
||||
// Roughly based on https://github.com/dotnet/winforms/pull/5375
|
||||
private bool IsParentInDesignMode(Control control)
|
||||
{
|
||||
if(control == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(control));
|
||||
}
|
||||
|
||||
//Check if our Site is in DesignMode
|
||||
//If not then walk up the tree
|
||||
//Until we find a Site that is or our parent is null
|
||||
if(control.Site?.DesignMode ?? false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if(control.Parent == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsParentInDesignMode(control.Parent);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.HandleCreated" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
|
||||
protected override void OnHandleCreated(EventArgs e)
|
||||
{
|
||||
designMode = DesignMode;
|
||||
|
||||
//Check if our Parent is in design mode.
|
||||
if (!designMode)
|
||||
{
|
||||
try
|
||||
{
|
||||
designMode = IsParentInDesignMode(this);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
//TODO: We should log the exception
|
||||
//Need to provide a wrapper around CEF Log first
|
||||
}
|
||||
}
|
||||
|
||||
if(designMode)
|
||||
{
|
||||
//For design mode only we remove our custom ApplicationExit event handler
|
||||
//As we must avoid making all unmanaged calls
|
||||
Application.ApplicationExit -= OnApplicationExit;
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeFieldsAndCefIfRequired();
|
||||
|
||||
// NOTE: Had to move the code out of this function otherwise the designer would crash
|
||||
CreateBrowser();
|
||||
|
||||
ResizeBrowser(Width, Height);
|
||||
}
|
||||
|
||||
base.OnHandleCreated(e);
|
||||
}
|
||||
|
||||
protected override void OnHandleDestroyed(EventArgs e)
|
||||
{
|
||||
if (!designMode)
|
||||
{
|
||||
// NOTE: Had to move the code out of this function otherwise the designer would crash
|
||||
OnHandleDestroyedInternal();
|
||||
}
|
||||
|
||||
base.OnHandleDestroyed(e);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void OnHandleDestroyedInternal()
|
||||
{
|
||||
//When the Control is being Recreated then we'll park
|
||||
//the browser (set to a temp parent) and assign to
|
||||
//our new handle when it's ready.
|
||||
if (RecreatingHandle || ParkControlOnHandleDestroyed)
|
||||
{
|
||||
parkingControl = new Control();
|
||||
parkingControl.CreateControl();
|
||||
|
||||
var host = this.GetBrowserHost();
|
||||
|
||||
// Possible host is null
|
||||
// https://github.com/cefsharp/CefSharp/issues/3931
|
||||
if (host != null)
|
||||
{
|
||||
var hwnd = host.GetWindowHandle();
|
||||
|
||||
NativeMethodWrapper.SetWindowParent(hwnd, parkingControl.Handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this method to handle creation of WindowInfo. This method can be used to customise aspects of
|
||||
/// browser creation including configuration of settings such as <see cref="IWindowInfo.ExStyle"/>.
|
||||
/// Window Activation is disabled by default, you can re-enable it by overriding and removing the
|
||||
/// WS_EX_NOACTIVATE style from <see cref="IWindowInfo.ExStyle"/>.
|
||||
/// </summary>
|
||||
/// <param name="handle">Window handle for the Control</param>
|
||||
/// <returns>Window Info</returns>
|
||||
/// <example>
|
||||
/// To re-enable Window Activation then remove WS_EX_NOACTIVATE from ExStyle
|
||||
/// <code>
|
||||
/// const uint WS_EX_NOACTIVATE = 0x08000000;
|
||||
/// windowInfo.ExStyle &= ~WS_EX_NOACTIVATE;
|
||||
///</code>
|
||||
/// </example>
|
||||
protected virtual IWindowInfo CreateBrowserWindowInfo(IntPtr handle)
|
||||
{
|
||||
var windowInfo = Core.ObjectFactory.CreateWindowInfo();
|
||||
windowInfo.SetAsChild(handle);
|
||||
|
||||
if (!ActivateBrowserOnCreation)
|
||||
{
|
||||
//Disable Window activation by default
|
||||
//https://github.com/chromiumembedded/cef/issues/1856/branch-2526-cef-activates-browser-window
|
||||
windowInfo.ExStyle |= WS_EX_NOACTIVATE;
|
||||
}
|
||||
|
||||
return windowInfo;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private void CreateBrowser()
|
||||
{
|
||||
browserCreated = true;
|
||||
|
||||
if (((IWebBrowserInternal)this).HasParent == false)
|
||||
{
|
||||
//If we are Recreating our handle we will have re-parented our
|
||||
//browser to parkingControl. We'll assign the browser to our newly
|
||||
//created handle now.
|
||||
if ((RecreatingHandle || ParkControlOnHandleDestroyed) && IsBrowserInitialized && browser != null)
|
||||
{
|
||||
var host = this.GetBrowserHost();
|
||||
var hwnd = host.GetWindowHandle();
|
||||
|
||||
NativeMethodWrapper.SetWindowParent(hwnd, Handle);
|
||||
|
||||
parkingControl.Dispose();
|
||||
parkingControl = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var windowInfo = CreateBrowserWindowInfo(Handle);
|
||||
|
||||
//We actually check if WS_EX_NOACTIVATE was set for instances
|
||||
//the user has override CreateBrowserWindowInfo and not called base.CreateBrowserWindowInfo
|
||||
removeExNoActivateStyle = (windowInfo.ExStyle & WS_EX_NOACTIVATE) == WS_EX_NOACTIVATE;
|
||||
|
||||
initialAddressLoaded = !string.IsNullOrEmpty(Address);
|
||||
|
||||
managedCefBrowserAdapter.CreateBrowser(windowInfo, browserSettings, requestContext, Address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from <see cref="OnAfterBrowserCreated(IBrowser)"/> when we set focus
|
||||
/// to the CefBrowser instance via <see cref="IBrowserHost.SetFocus(bool)"/>.
|
||||
/// Method is only called if the browser got focus via <see cref="OnGotFocus(EventArgs)"/>
|
||||
/// before the call to <see cref="OnAfterBrowserCreated(IBrowser)"/>.
|
||||
/// Can be overridden to provide custom behaviour.
|
||||
/// </summary>
|
||||
protected virtual void OnSetBrowserInitialFocus()
|
||||
{
|
||||
// MultiThreadedMessageLoop = true
|
||||
// Starting in M104 CEF changes mean that calling CefBrowserHost::SetFocus(true)
|
||||
// directly in OnAfterCreated result in the browser focus being in a strange state when using
|
||||
// MultiThreadedMessageLoop. Dealaying the SetFocus call results in the correct behaviour.
|
||||
// Here we Invoke back into the WinForms UI Thread, check if we have Focus then call
|
||||
// SetFocus (which will call back onto the CEF UI Thread).
|
||||
// It's possible to use Cef.PostAction to invoke directly on the CEF UI Thread,
|
||||
// this also seems to work as expected, using the WinForms UI Thread allows
|
||||
// us to check the Focused property to determine if we actully have focus
|
||||
// https://github.com/chromiumembedded/cef/issues/3436/chromium-based-browser-loses-focus-when
|
||||
if (InvokeRequired)
|
||||
{
|
||||
BeginInvoke((Action)(() =>
|
||||
{
|
||||
if (Disposing || IsDisposed || browser?.IsDisposed == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Focused)
|
||||
{
|
||||
browser?.GetHost()?.SetFocus(true);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after browser created.
|
||||
/// </summary>
|
||||
/// <param name="browser">The browser.</param>
|
||||
partial void OnAfterBrowserCreated(IBrowser browser)
|
||||
{
|
||||
BrowserHwnd = browser.GetHost().GetWindowHandle();
|
||||
|
||||
// By the time this callback gets called, this control
|
||||
// is most likely hooked into a browser Form of some sort.
|
||||
// (Which is what ParentFormMessageInterceptor relies on.)
|
||||
// Ensure the ParentFormMessageInterceptor construction occurs on the WinForms UI thread:
|
||||
if (UseParentFormMessageInterceptor)
|
||||
{
|
||||
this.InvokeOnUiThreadIfRequired(() =>
|
||||
{
|
||||
parentFormMessageInterceptor = new ParentFormMessageInterceptor(this);
|
||||
parentFormMessageInterceptor.Moving += (sender, args) =>
|
||||
{
|
||||
if (IsBrowserInitialized && !IsDisposed)
|
||||
{
|
||||
browser?.GetHost()?.NotifyMoveOrResizeStarted();
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
ResizeBrowser(Width, Height);
|
||||
|
||||
//If Load was called after the call to CreateBrowser we'll call Load
|
||||
//on the MainFrame
|
||||
if (!initialAddressLoaded && !string.IsNullOrEmpty(Address))
|
||||
{
|
||||
browser.MainFrame.LoadUrl(Address);
|
||||
}
|
||||
|
||||
if(initialFocus)
|
||||
{
|
||||
OnSetBrowserInitialFocus();
|
||||
}
|
||||
|
||||
RaiseIsBrowserInitializedChangedEvent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the address.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="AddressChangedEventArgs"/> instance containing the event data.</param>
|
||||
void IWebBrowserInternal.SetAddress(AddressChangedEventArgs args)
|
||||
{
|
||||
Address = args.Address;
|
||||
|
||||
var handler = AddressChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the loading state change.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="LoadingStateChangedEventArgs"/> instance containing the event data.</param>
|
||||
partial void SetLoadingStateChange(LoadingStateChangedEventArgs args)
|
||||
{
|
||||
CanGoBack = args.CanGoBack;
|
||||
CanGoForward = args.CanGoForward;
|
||||
IsLoading = args.IsLoading;
|
||||
|
||||
if (removeExNoActivateStyle && browser != null)
|
||||
{
|
||||
removeExNoActivateStyle = false;
|
||||
|
||||
var host = this.GetBrowserHost();
|
||||
var hwnd = host.GetWindowHandle();
|
||||
//Remove the WS_EX_NOACTIVATE style so that future mouse clicks inside the
|
||||
//browser correctly activate and focus the browser.
|
||||
//https://github.com/chromiumembedded/cef/blob/9df4a54308a88fd80c5774d91c62da35afb5fd1b/tests/cefclient/browser/root_window_win.cc#L1088
|
||||
NativeMethodWrapper.RemoveExNoActivateStyle(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the title.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="TitleChangedEventArgs"/> instance containing the event data.</param>
|
||||
void IWebBrowserInternal.SetTitle(TitleChangedEventArgs args)
|
||||
{
|
||||
var handler = TitleChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, args);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the tooltip text.
|
||||
/// </summary>
|
||||
/// <param name="tooltipText">The tooltip text.</param>
|
||||
void IWebBrowserInternal.SetTooltipText(string tooltipText)
|
||||
{
|
||||
TooltipText = tooltipText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manually implement Focused because cef does not implement it.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if focused; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>This is also how the Microsoft's WebBrowserControl implements the Focused property.</remarks>
|
||||
public override bool Focused
|
||||
{
|
||||
get
|
||||
{
|
||||
if (base.Focused)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!IsHandleCreated)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return NativeMethodWrapper.IsFocused(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void ResizeBrowser(int width, int height)
|
||||
{
|
||||
if (!designMode && IsBrowserInitialized)
|
||||
{
|
||||
managedCefBrowserAdapter.Resize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When minimized set the browser window size to 0x0 to reduce resource usage.
|
||||
/// https://github.com/chromiumembedded/cef/blob/c7701b8a6168f105f2c2d6b239ce3958da3e3f13/tests/cefclient/browser/browser_window_std_win.cc#L87
|
||||
/// </summary>
|
||||
internal override void HideInternal()
|
||||
{
|
||||
ResizeBrowser(0, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the browser (called after previous minimised)
|
||||
/// </summary>
|
||||
internal override void ShowInternal()
|
||||
{
|
||||
ResizeBrowser(Width, Height);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnGotFocus(EventArgs e)
|
||||
{
|
||||
if (IsBrowserInitialized)
|
||||
{
|
||||
browser.GetHost().SetFocus(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
initialFocus = true;
|
||||
}
|
||||
|
||||
base.OnGotFocus(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current IBrowser Instance
|
||||
/// </summary>
|
||||
/// <returns>browser instance</returns>
|
||||
public IBrowser GetBrowser()
|
||||
{
|
||||
ThrowExceptionIfDisposed();
|
||||
ThrowExceptionIfBrowserNotInitialized();
|
||||
|
||||
return browser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ChromiumWebBrowser"/> associated with
|
||||
/// a specific <see cref="IBrowser"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="browser">browser</param>
|
||||
/// <returns>returns the assocaited <see cref="ChromiumWebBrowser"/> or null if Disposed or no host found.</returns>
|
||||
public static ChromiumWebBrowser FromBrowser(IBrowser browser)
|
||||
{
|
||||
return FromBrowser<ChromiumWebBrowser>(browser);
|
||||
}
|
||||
}
|
||||
}
|
71
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/ChromiumWebBrowserDesigner.cs
vendored
Normal file
71
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/ChromiumWebBrowserDesigner.cs
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Copyright © 2018 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.Collections;
|
||||
using System.Drawing;
|
||||
#if NETCOREAPP
|
||||
using Microsoft.DotNet.DesignTools.Designers;
|
||||
#else
|
||||
using System.Windows.Forms.Design;
|
||||
#endif
|
||||
|
||||
namespace CefSharp.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// ChromiumWebBrowser Control Designer
|
||||
/// </summary>
|
||||
public class ChromiumWebBrowserDesigner : ControlDesigner
|
||||
{
|
||||
/// <summary>
|
||||
/// Receives a call when the control that the designer is managing has painted its surface so the designer can paint any additional adornments on top of the control.
|
||||
/// </summary>
|
||||
/// <param name="pe">args</param>
|
||||
protected override void OnPaintAdornments(System.Windows.Forms.PaintEventArgs pe)
|
||||
{
|
||||
//NOTE: Removed until a better image can be found, add image as Embedded Resource and update name below
|
||||
//var assembly = Assembly.GetAssembly(typeof(ChromiumWebBrowserDesigner));
|
||||
|
||||
//using (var logo = assembly.GetManifestResourceStream("CefSharp.WinForms.CefSharpLogo.png"))
|
||||
//using (var img = Image.FromStream(logo))
|
||||
//{
|
||||
// pe.Graphics.DrawImage(img, 0, 0);
|
||||
//}
|
||||
|
||||
using (var font = new Font("Arial", 16))
|
||||
using (var stringFormat = new StringFormat
|
||||
{
|
||||
// Create a StringFormat object with the each line of text, and the block
|
||||
// of text centered on the page.
|
||||
Alignment = StringAlignment.Center,
|
||||
LineAlignment = StringAlignment.Center
|
||||
})
|
||||
{
|
||||
pe.Graphics.DrawString("ChromiumWebBrowser", font, Brushes.Black, pe.ClipRectangle, stringFormat);
|
||||
}
|
||||
|
||||
base.OnPaintAdornments(pe);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts the set of properties the component exposes through a TypeDescriptor.
|
||||
/// </summary>
|
||||
/// <param name="properties">properties</param>
|
||||
protected override void PreFilterProperties(IDictionary properties)
|
||||
{
|
||||
//Remove some of the default properties from the designer
|
||||
//they don't have much meaning for the browser
|
||||
//Probably more that can be removed/tweaked
|
||||
properties.Remove("BackgroundImage");
|
||||
properties.Remove("BackgroundImageLayout");
|
||||
properties.Remove("Text");
|
||||
|
||||
properties.Remove("Font");
|
||||
properties.Remove("ForeColor");
|
||||
properties.Remove("BackColor");
|
||||
properties.Remove("RightToLeft");
|
||||
|
||||
base.PreFilterProperties(properties);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// Copyright © 2015 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;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace CefSharp.WinForms.Experimental
|
||||
{
|
||||
/// <summary>
|
||||
/// ChromiumWidgetHandleFinder is a helper class used to find the <see cref="ChromeRenderWidgetHostClassName"/>
|
||||
/// child Hwnd for the browser instance.
|
||||
/// </summary>
|
||||
public static class ChromiumRenderWidgetHandleFinder
|
||||
{
|
||||
/// <summary>
|
||||
/// Class Name of the Chrome_RenderWidgetHostHWND Child Window
|
||||
/// </summary>
|
||||
public const string ChromeRenderWidgetHostClassName = "Chrome_RenderWidgetHostHWND";
|
||||
|
||||
/// <summary>
|
||||
/// EnumWindowProc delegate used by <see cref="EnumChildWindows(IntPtr, EnumWindowProc, IntPtr)"/>
|
||||
/// </summary>
|
||||
/// <param name="hwnd">A handle to a child window of the parent window specified in EnumChildWindows</param>
|
||||
/// <param name="lParam">The application-defined value given in EnumChildWindows</param>
|
||||
/// <returns>To continue enumeration, the callback function must return true; to stop enumeration, it must return false.</returns>
|
||||
private delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
|
||||
|
||||
[DllImport("user32")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
||||
|
||||
/// <summary>
|
||||
/// Chromium's message-loop Window isn't created synchronously, so this may not find it.
|
||||
/// If so, you need to wait and try again later.
|
||||
/// </summary>
|
||||
/// <param name="chromiumWebBrowser">ChromiumWebBrowser instance</param>
|
||||
/// <param name="chromerRenderWidgetHostHandle">Handle of the child HWND with the name <see cref="ChromeRenderWidgetHostClassName"/></param>
|
||||
/// <returns>returns true if the HWND was found otherwise false.</returns>
|
||||
public static bool TryFindHandle(IWebBrowser chromiumWebBrowser, out IntPtr chromerRenderWidgetHostHandle)
|
||||
{
|
||||
var host = chromiumWebBrowser.GetBrowserHost();
|
||||
if (host == null)
|
||||
{
|
||||
throw new Exception("IBrowserHost is null, you've likely call this method before the underlying browser has been created.");
|
||||
}
|
||||
|
||||
var hwnd = host.GetWindowHandle();
|
||||
|
||||
return TryFindHandle(hwnd, ChromeRenderWidgetHostClassName, out chromerRenderWidgetHostHandle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chromium's message-loop Window isn't created synchronously, so this may not find it.
|
||||
/// If so, you need to wait and try again later.
|
||||
/// </summary>
|
||||
/// <param name="browser">IBrowser instance</param>
|
||||
/// <param name="chromerRenderWidgetHostHandle">Handle of the child HWND with the name <see cref="ChromeRenderWidgetHostClassName"/></param>
|
||||
/// <returns>returns true if the HWND was found otherwise false.</returns>
|
||||
public static bool TryFindHandle(IBrowser browser, out IntPtr chromerRenderWidgetHostHandle)
|
||||
{
|
||||
var host = browser.GetHost();
|
||||
if (host == null)
|
||||
{
|
||||
throw new Exception("IBrowserHost is null, you've likely call this method before the underlying browser has been created.");
|
||||
}
|
||||
|
||||
var hwnd = host.GetWindowHandle();
|
||||
|
||||
return TryFindHandle(hwnd, ChromeRenderWidgetHostClassName, out chromerRenderWidgetHostHandle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function used to find the child HWND with the ClassName matching <paramref name="chromeRenderWidgetHostClassName"/>
|
||||
/// Chromium's message-loop Window isn't created synchronously, so this may not find it.
|
||||
/// If so, you need to wait and try again later.
|
||||
/// In most cases you should use the <see cref="TryFindHandle(IWebBrowser, out IntPtr)"/> overload.
|
||||
/// </summary>
|
||||
/// <param name="chromiumWebBrowserHandle"><see cref="ChromiumWebBrowser"/> control Handle</param>
|
||||
/// <param name="chromeRenderWidgetHostClassName">class name used to match</param>
|
||||
/// <param name="chromerRenderWidgetHostHandle">Handle of the child HWND with the name <see cref="ChromeRenderWidgetHostClassName"/></param>
|
||||
/// <returns>returns true if the HWND was found otherwise false.</returns>
|
||||
public static bool TryFindHandle(IntPtr chromiumWebBrowserHandle, string chromeRenderWidgetHostClassName, out IntPtr chromerRenderWidgetHostHandle)
|
||||
{
|
||||
var chromeRenderWidgetHostHwnd = IntPtr.Zero;
|
||||
|
||||
EnumWindowProc childProc = (IntPtr hWnd, IntPtr lParam) =>
|
||||
{
|
||||
var buffer = new StringBuilder(128);
|
||||
GetClassName(hWnd, buffer, buffer.Capacity);
|
||||
|
||||
if (buffer.ToString() == chromeRenderWidgetHostClassName)
|
||||
{
|
||||
chromeRenderWidgetHostHwnd = hWnd;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
EnumChildWindows(chromiumWebBrowserHandle, childProc, IntPtr.Zero);
|
||||
|
||||
chromerRenderWidgetHostHandle = chromeRenderWidgetHostHwnd;
|
||||
|
||||
return chromerRenderWidgetHostHandle != IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright © 2015 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;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CefSharp.WinForms.Experimental
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a convenient <see cref="NativeWindow"/> implement
|
||||
/// that can be used without having to create your own class
|
||||
/// </summary>
|
||||
public class ChromiumWidgetNativeWindow : NativeWindow
|
||||
{
|
||||
private Func<Message, bool> wndProcHandler;
|
||||
|
||||
/// <summary>
|
||||
/// ChromiumWidgetMessageInterceptor constructor
|
||||
/// </summary>
|
||||
/// <param name="control">Control is used to handled the <see cref="Control.HandleDestroyed"/> event so
|
||||
/// we can automatically call <see cref="NativeWindow.ReleaseHandle"/>. If null then you are responsible
|
||||
/// for calling <see cref="NativeWindow.ReleaseHandle"/></param>
|
||||
/// <param name="chromeWidgetHostHandle">Hwnd to intercept messages for.</param>
|
||||
public ChromiumWidgetNativeWindow(Control control, IntPtr chromeWidgetHostHandle)
|
||||
{
|
||||
AssignHandle(chromeWidgetHostHandle);
|
||||
|
||||
if (control != null)
|
||||
{
|
||||
control.HandleDestroyed += BrowserHandleDestroyed;
|
||||
}
|
||||
}
|
||||
|
||||
private void BrowserHandleDestroyed(object sender, EventArgs e)
|
||||
{
|
||||
ReleaseHandle();
|
||||
|
||||
var control = (Control)sender;
|
||||
|
||||
control.HandleDestroyed -= BrowserHandleDestroyed;
|
||||
wndProcHandler = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register a Func which is used to intercept <see cref="WndProc(ref Message)"/>
|
||||
/// calls. <paramref name="wndProcHandler"/> should return true if the message
|
||||
/// was handled, otherwise false.
|
||||
/// </summary>
|
||||
/// <param name="wndProcHandler">Func to be used to intercept messages, null to clear an existing function.</param>
|
||||
public void OnWndProc(Func<Message, bool> wndProcHandler)
|
||||
{
|
||||
this.wndProcHandler = wndProcHandler;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
var handler = wndProcHandler;
|
||||
|
||||
var handled = handler?.Invoke(m);
|
||||
|
||||
if (handled == false)
|
||||
{
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
76
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/DisplayHandler.cs
vendored
Normal file
76
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/DisplayHandler.cs
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Copyright © 2021 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 CefSharp.WinForms.Host;
|
||||
|
||||
namespace CefSharp.WinForms.Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// A WinForms Specific <see cref="IDisplayHandler"/> implementation that simplifies
|
||||
/// the process of hosting a Popup as a Control/Tab. Use this implementation as a base
|
||||
/// for your own custom implementation if you are using <see cref="LifeSpanHandler.Create"/>
|
||||
/// </summary>
|
||||
public class DisplayHandler : CefSharp.Handler.DisplayHandler
|
||||
{
|
||||
/// <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);
|
||||
}
|
||||
|
||||
/// <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 OnTitleChanged(IWebBrowser chromiumWebBrowser, TitleChangedEventArgs args)
|
||||
{
|
||||
var browser = args.Browser;
|
||||
|
||||
if (browser.IsPopup)
|
||||
{
|
||||
var control = ChromiumHostControl.FromBrowser(browser);
|
||||
|
||||
control?.OnTitleChanged(args);
|
||||
}
|
||||
|
||||
base.OnTitleChanged(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);
|
||||
}
|
||||
}
|
||||
}
|
330
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/LifeSpanHandler.cs
vendored
Normal file
330
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/LifeSpanHandler.cs
vendored
Normal file
|
@ -0,0 +1,330 @@
|
|||
// Copyright © 2021 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using CefSharp.WinForms.Host;
|
||||
using CefSharp.WinForms.Internals;
|
||||
|
||||
namespace CefSharp.WinForms.Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called <b>before</b>the popup is created, can be used to cancel popup creation if required
|
||||
/// or modify <see cref="IBrowserSettings"/>.
|
||||
/// It's important to note that the methods of this interface are called on a CEF UI thread,
|
||||
/// which by default is not the same as your application UI thread.
|
||||
/// </summary>
|
||||
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control</param>
|
||||
/// <param name="browser">The browser instance that launched this popup.</param>
|
||||
/// <param name="frame">The HTML frame that launched this popup.</param>
|
||||
/// <param name="targetUrl">The URL of the popup content. (This may be empty/null)</param>
|
||||
/// <param name="targetFrameName">The name of the popup. (This may be empty/null)</param>
|
||||
/// <param name="targetDisposition">The value indicates where the user intended to
|
||||
/// open the popup (e.g. current tab, new tab, etc)</param>
|
||||
/// <param name="userGesture">The value will be true if the popup was opened via explicit user gesture
|
||||
/// (e.g. clicking a link) or false if the popup opened automatically (e.g. via the DomContentLoaded event).</param>
|
||||
/// <param name="browserSettings">browser settings, defaults to source browsers</param>
|
||||
/// <returns>To cancel creation of the popup return true otherwise return false.</returns>
|
||||
public delegate PopupCreation OnBeforePopupCreatedDelegate(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IBrowserSettings browserSettings);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the <see cref="ChromiumHostControl"/> has been created.
|
||||
/// When called you must add the control to it's intended parent
|
||||
/// so the <see cref="Control.ClientRectangle"/> can be calculated to set the initial
|
||||
/// size correctly.
|
||||
/// </summary>
|
||||
/// <param name="control">popup host control</param>
|
||||
/// <param name="url">url</param>
|
||||
public delegate void OnPopupCreatedDelegate(ChromiumHostControl control, string url);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the <see cref="IBrowser"/> instance has been created.
|
||||
/// The <see cref="IBrowser"/> reference will be valid until <see cref="OnPopupDestroyedDelegate"/> is called
|
||||
/// </summary>
|
||||
/// <param name="control">popup host control, maybe null if Browser is hosted in a native Popup window.
|
||||
/// DevTools by default will be hosted in a native popup window.</param>
|
||||
/// <param name="browser">browser</param>
|
||||
public delegate void OnPopupBrowserCreatedDelegate(ChromiumHostControl control, IBrowser browser);
|
||||
|
||||
/// <summary>
|
||||
/// Called when the <see cref="ChromiumHostControl"/> is to be removed from it's parent.
|
||||
/// When called you must remove/dispose of the <see cref="ChromiumHostControl"/>.
|
||||
/// </summary>
|
||||
/// <param name="control">popup host control</param>
|
||||
/// <param name="browser">browser</param>
|
||||
public delegate void OnPopupDestroyedDelegate(ChromiumHostControl control, IBrowser browser);
|
||||
|
||||
/// <summary>
|
||||
/// Called to create a new instance of <see cref="ChromiumHostControl"/>. Allows creation of a derived
|
||||
/// implementation of <see cref="ChromiumHostControl"/>.
|
||||
/// </summary>
|
||||
/// <returns>A custom instance of <see cref="ChromiumHostControl"/>.</returns>
|
||||
public delegate ChromiumHostControl CreatePopupChromiumHostControl();
|
||||
|
||||
/// <summary>
|
||||
/// A WinForms Specific <see cref="ILifeSpanHandler"/> implementation that simplifies
|
||||
/// the process of hosting a Popup as a Control/Tab.
|
||||
/// This <see cref="ILifeSpanHandler"/> implementation returns true in <see cref="ILifeSpanHandler.DoClose(IWebBrowser, IBrowser)"/>
|
||||
/// so no WM_CLOSE message is sent, this differs from the default CEF behaviour.
|
||||
/// </summary>
|
||||
public class LifeSpanHandler : CefSharp.Handler.LifeSpanHandler
|
||||
{
|
||||
private readonly Dictionary<int, ParentFormMessageInterceptor> popupParentFormMessageInterceptors = new Dictionary<int, ParentFormMessageInterceptor>();
|
||||
private OnBeforePopupCreatedDelegate onBeforePopupCreated;
|
||||
private OnPopupDestroyedDelegate onPopupDestroyed;
|
||||
private OnPopupBrowserCreatedDelegate onPopupBrowserCreated;
|
||||
private OnPopupCreatedDelegate onPopupCreated;
|
||||
private CreatePopupChromiumHostControl chromiumHostControlCreatedDelegate;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
/// <param name="chromiumHostControlCreatedDelegate">Optional delegate used to create custom <see cref="ChromiumHostControl"/> instances.</param>
|
||||
public LifeSpanHandler(CreatePopupChromiumHostControl chromiumHostControlCreatedDelegate = null)
|
||||
{
|
||||
this.chromiumHostControlCreatedDelegate = chromiumHostControlCreatedDelegate;
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
try
|
||||
{
|
||||
//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);
|
||||
|
||||
control.Dispose();
|
||||
}));
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
// If the popup is being hosted on a Form that is being
|
||||
// Closed/Disposed as we attempt to call Control.Invoke
|
||||
// we can end up with an ObjectDisposedException
|
||||
// return false (Default behaviour).
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//No WM_CLOSE message will be sent, manually handle closing
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
|
||||
{
|
||||
if (!browser.IsDisposed && browser.IsPopup)
|
||||
{
|
||||
ParentFormMessageInterceptor interceptor;
|
||||
|
||||
if (popupParentFormMessageInterceptors.TryGetValue(browser.Identifier, out interceptor))
|
||||
{
|
||||
popupParentFormMessageInterceptors.Remove(browser.Identifier);
|
||||
interceptor?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnBeforePopupCreatedDelegate"/> will be called <b>before</b> the popup has been created and
|
||||
/// can be used to cancel popup creation if required or modify <see cref="IBrowserSettings"/>.
|
||||
/// </summary>
|
||||
/// <param name="onBeforePopupCreated">Action to be invoked before popup is created.</param>
|
||||
/// <returns><see cref="LifeSpanHandler"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandler OnBeforePopupCreated(OnBeforePopupCreatedDelegate onBeforePopupCreated)
|
||||
{
|
||||
this.onBeforePopupCreated = onBeforePopupCreated;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnPopupCreatedDelegate"/> will be called when the<see cref="ChromiumHostControl"/> has been
|
||||
/// created. When the <see cref="OnPopupCreatedDelegate"/> is called you must add the control to it's intended parent
|
||||
/// so the <see cref="Control.ClientRectangle"/> can be calculated to set the initial
|
||||
/// size correctly.
|
||||
/// </summary>
|
||||
/// <param name="onPopupCreated">Action to be invoked when the Popup host has been created and is ready to be attached to it's parent.</param>
|
||||
/// <returns><see cref="LifeSpanHandler"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandler OnPopupCreated(OnPopupCreatedDelegate onPopupCreated)
|
||||
{
|
||||
this.onPopupCreated = onPopupCreated;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnPopupBrowserCreatedDelegate"/> will be called when the<see cref="IBrowser"/> has been
|
||||
/// created. The <see cref="IBrowser"/> instance is valid until <see cref="OnPopupDestroyed(OnPopupDestroyedDelegate)"/>
|
||||
/// is called. <see cref="IBrowser"/> provides low level access to the CEF Browser, you can access frames, view source,
|
||||
/// perform navigation (via frame) etc.
|
||||
/// </summary>
|
||||
/// <param name="onPopupBrowserCreated">Action to be invoked when the <see cref="IBrowser"/> has been created.</param>
|
||||
/// <returns><see cref="LifeSpanHandler"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandler OnPopupBrowserCreated(OnPopupBrowserCreatedDelegate onPopupBrowserCreated)
|
||||
{
|
||||
this.onPopupBrowserCreated = onPopupBrowserCreated;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnPopupDestroyedDelegate"/> will be called when the <see cref="ChromiumHostControl"/> is to be
|
||||
/// removed from it's parent.
|
||||
/// When the <see cref="OnPopupDestroyedDelegate"/> is called you must remove/dispose of the <see cref="ChromiumHostControl"/>.
|
||||
/// </summary>
|
||||
/// <param name="onPopupDestroyed">Action to be invoked when the Popup is to be destroyed.</param>
|
||||
/// <returns><see cref="LifeSpanHandler"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandler OnPopupDestroyed(OnPopupDestroyedDelegate onPopupDestroyed)
|
||||
{
|
||||
this.onPopupDestroyed = onPopupDestroyed;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of the <see cref="LifeSpanHandlerBuilder"/>
|
||||
/// which can be used to create a WinForms specific <see cref="ILifeSpanHandler"/>
|
||||
/// implementation that simplifies the process of hosting a Popup as a Control/Tab.
|
||||
/// In scnarios where you also need to implement <see cref="ILoadHandler"/> then instead
|
||||
/// of implementing directly you will need to inherit from <see cref="CefSharp.WinForms.Handler.LoadHandler"/>.
|
||||
/// As it provides base functionality required to make <see cref="ChromiumHostControl"/> events work correctly.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="LifeSpanHandlerBuilder"/> which can be used to fluently create an <see cref="ILifeSpanHandler"/>.
|
||||
/// Call <see cref="LifeSpanHandlerBuilder.Build"/> to create the actual instance after you have call
|
||||
/// <see cref="LifeSpanHandlerBuilder.OnPopupCreated(OnPopupCreatedDelegate)"/> etc.
|
||||
/// </returns>
|
||||
public static LifeSpanHandlerBuilder Create(CreatePopupChromiumHostControl chromiumHostControlCreatedDelegate = null)
|
||||
{
|
||||
return new LifeSpanHandlerBuilder(chromiumHostControlCreatedDelegate);
|
||||
}
|
||||
}
|
||||
}
|
95
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/LifeSpanHandlerBuilder.cs
vendored
Normal file
95
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/LifeSpanHandlerBuilder.cs
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
// Copyright © 2021 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.
|
||||
|
||||
namespace CefSharp.WinForms.Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// Fluent <see cref="CefSharp.WinForms.Handler.LifeSpanHandler"/> Builder
|
||||
/// </summary>
|
||||
public class LifeSpanHandlerBuilder
|
||||
{
|
||||
private readonly LifeSpanHandler handler;
|
||||
|
||||
/// <summary>
|
||||
/// LifeSpanHandlerBuilder
|
||||
/// </summary>
|
||||
/// <param name="chromiumHostControlCreatedDelegate">
|
||||
/// When specified the delegate will be used to create the <see cref="Host.ChromiumHostControl"/>
|
||||
/// instance. Allowing users to create their own custom instance that extends <see cref="Host.ChromiumHostControl"/>
|
||||
/// </param>
|
||||
public LifeSpanHandlerBuilder(CreatePopupChromiumHostControl chromiumHostControlCreatedDelegate)
|
||||
{
|
||||
handler = new LifeSpanHandler(chromiumHostControlCreatedDelegate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnBeforePopupCreatedDelegate"/> will be called <b>before</b> the popup has been created and
|
||||
/// can be used to cancel popup creation if required, modify <see cref="IBrowserSettings"/> and disable javascript.
|
||||
/// </summary>
|
||||
/// <param name="onBeforePopupCreated">Action to be invoked before popup is created.</param>
|
||||
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandlerBuilder OnBeforePopupCreated(OnBeforePopupCreatedDelegate onBeforePopupCreated)
|
||||
{
|
||||
handler.OnBeforePopupCreated(onBeforePopupCreated);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnPopupCreatedDelegate"/> will be called when the<see cref="Host.ChromiumHostControl"/> has been
|
||||
/// created. When the <see cref="OnPopupCreatedDelegate"/> is called you must add the control to it's intended parent
|
||||
/// so the <see cref="System.Windows.Forms.Control.ClientRectangle"/> can be calculated to set the initial
|
||||
/// size correctly.
|
||||
/// </summary>
|
||||
/// <param name="onPopupCreated">Action to be invoked when the Popup is to be destroyed.</param>
|
||||
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandlerBuilder OnPopupCreated(OnPopupCreatedDelegate onPopupCreated)
|
||||
{
|
||||
handler.OnPopupCreated(onPopupCreated);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnPopupBrowserCreatedDelegate"/> will be called when the<see cref="IBrowser"/> has been
|
||||
/// created. The <see cref="IBrowser"/> instance is valid until <see cref="OnPopupDestroyed(OnPopupDestroyedDelegate)"/>
|
||||
/// is called. <see cref="IBrowser"/> provides low level access to the CEF Browser, you can access frames, view source,
|
||||
/// perform navigation (via frame) etc.
|
||||
/// </summary>
|
||||
/// <param name="onPopupBrowserCreated">Action to be invoked when the <see cref="IBrowser"/> has been created.</param>
|
||||
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandlerBuilder OnPopupBrowserCreated(OnPopupBrowserCreatedDelegate onPopupBrowserCreated)
|
||||
{
|
||||
handler.OnPopupBrowserCreated(onPopupBrowserCreated);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OnPopupDestroyedDelegate"/> will be called when the <see cref="Host.ChromiumHostControl"/> is to be
|
||||
/// removed from it's parent.
|
||||
/// When the <see cref="OnPopupDestroyedDelegate"/> is called you must remove/dispose of the <see cref="Host.ChromiumHostControl"/>.
|
||||
/// </summary>
|
||||
/// <param name="onPopupDestroyed">Action to be invoked when the Popup is to be destroyed.</param>
|
||||
/// <returns><see cref="LifeSpanHandlerBuilder"/> instance allowing you to chain method calls together</returns>
|
||||
public LifeSpanHandlerBuilder OnPopupDestroyed(OnPopupDestroyedDelegate onPopupDestroyed)
|
||||
{
|
||||
handler.OnPopupDestroyed(onPopupDestroyed);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="ILifeSpanHandler"/> implementation
|
||||
/// that can be used to host popups as tabs/controls. The resulting
|
||||
/// <see cref="ILifeSpanHandler"/> returns true in <see cref="ILifeSpanHandler.DoClose(IWebBrowser, IBrowser)"/>
|
||||
/// so no WM_CLOSE message is sent, this differs from the default CEF behaviour.
|
||||
/// </summary>
|
||||
/// <returns>a <see cref="ILifeSpanHandler"/> instance</returns>
|
||||
public ILifeSpanHandler Build()
|
||||
{
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
}
|
76
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/LoadHandler.cs
vendored
Normal file
76
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/LoadHandler.cs
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
// Copyright © 2021 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 CefSharp.WinForms.Host;
|
||||
|
||||
namespace CefSharp.WinForms.Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// A WinForms Specific <see cref="ILoadHandler"/> implementation that simplifies
|
||||
/// the process of hosting a Popup as a Control/Tab.Use this implementation as a base
|
||||
/// for your own custom implementation if you are using <see cref="LifeSpanHandler.Create"/>
|
||||
/// </summary>
|
||||
public class LoadHandler : CefSharp.Handler.LoadHandler
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void OnFrameLoadEnd(IWebBrowser chromiumWebBrowser, FrameLoadEndEventArgs args)
|
||||
{
|
||||
var browser = args.Browser;
|
||||
|
||||
if (browser.IsPopup)
|
||||
{
|
||||
var control = ChromiumHostControl.FromBrowser(browser);
|
||||
|
||||
control?.OnFrameLoadEnd(args);
|
||||
}
|
||||
|
||||
base.OnFrameLoadEnd(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 OnLoadError(IWebBrowser chromiumWebBrowser, LoadErrorEventArgs args)
|
||||
{
|
||||
var browser = args.Browser;
|
||||
|
||||
if (browser.IsPopup)
|
||||
{
|
||||
var control = ChromiumHostControl.FromBrowser(browser);
|
||||
|
||||
control?.OnLoadError(args);
|
||||
}
|
||||
|
||||
base.OnLoadError(chromiumWebBrowser, args);
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
}
|
25
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/PopupCreation.cs
vendored
Normal file
25
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Handler/PopupCreation.cs
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright © 2022 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.
|
||||
|
||||
namespace CefSharp.WinForms.Handler
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup Creation options
|
||||
/// </summary>
|
||||
public enum PopupCreation
|
||||
{
|
||||
/// <summary>
|
||||
/// Popup creation is cancled, no further action will occur
|
||||
/// </summary>
|
||||
Cancel = 0,
|
||||
/// <summary>
|
||||
/// Popup creation will continue as per normal.
|
||||
/// </summary>
|
||||
Continue,
|
||||
/// <summary>
|
||||
/// Popup creation will continue with javascript disabled.
|
||||
/// </summary>
|
||||
ContinueWithJavascriptDisabled
|
||||
}
|
||||
}
|
314
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Host/ChromiumHostControl.cs
vendored
Normal file
314
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Host/ChromiumHostControl.cs
vendored
Normal file
|
@ -0,0 +1,314 @@
|
|||
// Copyright © 2021 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;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CefSharp.WinForms.Host
|
||||
{
|
||||
/// <summary>
|
||||
/// Chromium Browser Host Control, used for hosting Popups in WinForms
|
||||
/// </summary>
|
||||
/// <seealso cref="Control" />
|
||||
[Docking(DockingBehavior.AutoDock), ToolboxBitmap(typeof(ChromiumWebBrowser)),
|
||||
Designer(typeof(ChromiumWebBrowserDesigner))]
|
||||
public class ChromiumHostControl : ChromiumHostControlBase, IWinFormsChromiumWebBrowser
|
||||
{
|
||||
/// <summary>
|
||||
/// Get access to the core <see cref="IBrowser"/> instance.
|
||||
/// Maybe null if the underlying CEF Browser has not yet been
|
||||
/// created or if this control has been disposed. Check
|
||||
/// <see cref="IBrowser.IsDisposed"/> before accessing.
|
||||
/// </summary>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(null)]
|
||||
public IBrowser BrowserCore { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event handler that will get called when the resource load for a navigation fails or is canceled.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler<LoadErrorEventArgs> LoadError;
|
||||
/// <summary>
|
||||
/// Event handler that will get called when the browser begins loading a frame. Multiple frames may be loading at the same
|
||||
/// time. Sub-frames may start or continue loading after the main frame load has ended. This method may not be called for a
|
||||
/// particular frame if the load request for that frame fails. For notification of overall browser load status use
|
||||
/// OnLoadingStateChange instead.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
/// <remarks>Whilst this may seem like a logical place to execute js, it's called before the DOM has been loaded, implement
|
||||
/// <see cref="IRenderProcessMessageHandler.OnContextCreated" /> as it's called when the underlying V8Context is created
|
||||
/// </remarks>
|
||||
public event EventHandler<FrameLoadStartEventArgs> FrameLoadStart;
|
||||
/// <summary>
|
||||
/// Event handler that will get called when the browser is done loading a frame. Multiple frames may be loading at the same
|
||||
/// time. Sub-frames may start or continue loading after the main frame load has ended. This method will always be called
|
||||
/// for all frames irrespective of whether the request completes successfully.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler<FrameLoadEndEventArgs> FrameLoadEnd;
|
||||
/// <summary>
|
||||
/// Event handler that will get called when the Loading state has changed.
|
||||
/// This event will be fired twice. Once when loading is initiated either programmatically or
|
||||
/// by user action, and once when loading is terminated due to completion, cancellation of failure.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler<LoadingStateChangedEventArgs> LoadingStateChanged;
|
||||
/// <summary>
|
||||
/// Event handler for receiving Javascript console messages being sent from web pages.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// (The exception to this is when you're running with settings.MultiThreadedMessageLoop = false, then they'll be the same thread).
|
||||
/// </summary>
|
||||
public event EventHandler<ConsoleMessageEventArgs> ConsoleMessage;
|
||||
/// <summary>
|
||||
/// Event handler for changes to the status message.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang.
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// (The exception to this is when you're running with settings.MultiThreadedMessageLoop = false, then they'll be the same thread).
|
||||
/// </summary>
|
||||
public event EventHandler<StatusMessageEventArgs> StatusMessage;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the browser address changed.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler<AddressChangedEventArgs> AddressChanged;
|
||||
/// <summary>
|
||||
/// Occurs when the browser title changed.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler<TitleChangedEventArgs> TitleChanged;
|
||||
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the control is currently loading one or more web pages (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is loading; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool IsLoading { get; private set; }
|
||||
/// <summary>
|
||||
/// The address (URL) which the browser control is currently displaying.
|
||||
/// Will automatically be updated as the user navigates to another page (e.g. by clicking on a link).
|
||||
/// </summary>
|
||||
/// <value>The address.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(null)]
|
||||
public string Address { get; private set; }
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the state of the control currently supports the GoForward action (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance can go forward; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool CanGoForward { get; private set; }
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the state of the control current supports the GoBack action (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance can go back; otherwise, <c>false</c>.</value>
|
||||
/// <remarks>In the WPF control, this property is implemented as a Dependency Property and fully supports data
|
||||
/// binding.</remarks>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool CanGoBack { get; private set; }
|
||||
/// <summary>
|
||||
/// A flag that indicates whether the WebBrowser is initialized (true) or not (false).
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is browser initialized; otherwise, <c>false</c>.</value>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool IsBrowserInitialized
|
||||
{
|
||||
get { return BrowserCore != null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:FrameLoadStart" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="FrameLoadStartEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnFrameLoadStart(FrameLoadStartEventArgs args)
|
||||
{
|
||||
FrameLoadStart?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:FrameLoadEnd" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="FrameLoadEndEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnFrameLoadEnd(FrameLoadEndEventArgs args)
|
||||
{
|
||||
FrameLoadEnd?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:ConsoleMessage" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="ConsoleMessageEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnConsoleMessage(ConsoleMessageEventArgs args)
|
||||
{
|
||||
ConsoleMessage?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:StatusMessage" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="StatusMessageEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnStatusMessage(StatusMessageEventArgs args)
|
||||
{
|
||||
StatusMessage?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:LoadError" /> event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="LoadErrorEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnLoadError(LoadErrorEventArgs args)
|
||||
{
|
||||
LoadError?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the loading state change.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="LoadingStateChangedEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnLoadingStateChange(LoadingStateChangedEventArgs args)
|
||||
{
|
||||
CanGoBack = args.CanGoBack;
|
||||
CanGoForward = args.CanGoForward;
|
||||
IsLoading = args.IsLoading;
|
||||
|
||||
LoadingStateChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the title.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="TitleChangedEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnTitleChanged(TitleChangedEventArgs args)
|
||||
{
|
||||
TitleChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the address.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="AddressChangedEventArgs"/> instance containing the event data.</param>
|
||||
internal void OnAddressChanged(AddressChangedEventArgs args)
|
||||
{
|
||||
Address = args.Address;
|
||||
|
||||
AddressChanged?.Invoke(this, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Loads the specified <paramref name="url"/> in the Main Frame.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL to be loaded.</param>
|
||||
public void LoadUrl(string url)
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var browser = BrowserCore;
|
||||
|
||||
if (browser == null || browser.IsDisposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using (var frame = browser.MainFrame)
|
||||
{
|
||||
frame.LoadUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<LoadUrlAsyncResponse> LoadUrlAsync(string url)
|
||||
{
|
||||
//LoadUrlAsync is actually a static method so that CefSharp.Wpf.HwndHost can reuse the code
|
||||
return CefSharp.WebBrowserExtensions.LoadUrlAsync(this, url);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<WaitForNavigationAsyncResponse> WaitForNavigationAsync(TimeSpan? timeout = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
//WaitForNavigationAsync is actually a static method so that CefSharp.Wpf.HwndHost can reuse the code
|
||||
return CefSharp.WebBrowserExtensions.WaitForNavigationAsync(this, timeout, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the main (top-level) frame for the browser window.
|
||||
/// </summary>
|
||||
/// <returns> the main frame</returns>
|
||||
public IFrame GetMainFrame()
|
||||
{
|
||||
var browser = BrowserCore;
|
||||
|
||||
if(browser == null)
|
||||
{
|
||||
throw new Exception(CefSharp.WebBrowserExtensions.BrowserNullExceptionString);
|
||||
}
|
||||
|
||||
return browser.MainFrame;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
var browserCore = BrowserCore;
|
||||
|
||||
AddressChanged = null;
|
||||
ConsoleMessage = null;
|
||||
FrameLoadEnd = null;
|
||||
FrameLoadStart = null;
|
||||
LoadError = null;
|
||||
LoadingStateChanged = null;
|
||||
StatusMessage = null;
|
||||
TitleChanged = null;
|
||||
BrowserCore = null;
|
||||
|
||||
if (browserCore?.IsDisposed == false)
|
||||
{
|
||||
//Close the underlying CEF Browser
|
||||
browserCore?.GetHost()?.CloseBrowser(true);
|
||||
}
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ChromiumHostControl"/> associated with
|
||||
/// a specific <see cref="IBrowser"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="browser">browser</param>
|
||||
/// <returns>returns the assocaited <see cref="ChromiumHostControl"/> or null if Disposed or no host found.</returns>
|
||||
public static ChromiumHostControl FromBrowser(IBrowser browser)
|
||||
{
|
||||
return FromBrowser<ChromiumHostControl>(browser);
|
||||
}
|
||||
}
|
||||
}
|
222
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Host/ChromiumHostControlBase.cs
vendored
Normal file
222
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Host/ChromiumHostControlBase.cs
vendored
Normal file
|
@ -0,0 +1,222 @@
|
|||
// Copyright © 2021 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;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CefSharp.WinForms.Host
|
||||
{
|
||||
/// <summary>
|
||||
/// Chromium Browser Host Control, provides base functionality for hosting a
|
||||
/// CefBrowser instance (main browser and popups) in WinForms.
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Windows.Forms.Control" />
|
||||
public abstract class ChromiumHostControlBase : Control
|
||||
{
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
||||
|
||||
/// <summary>
|
||||
/// IntPtr that represents the CefBrowser Hwnd
|
||||
/// Used for sending messages to the browser
|
||||
/// e.g. resize
|
||||
/// </summary>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
||||
public IntPtr BrowserHwnd { get; set; }
|
||||
/// <summary>
|
||||
/// Set to true while handing an activating WM_ACTIVATE message.
|
||||
/// MUST ONLY be cleared by DefaultFocusHandler.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if this instance is activating; otherwise, <c>false</c>.</value>
|
||||
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), DefaultValue(false)]
|
||||
public bool IsActivating { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Event called after the underlying CEF browser instance has been created.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
public event EventHandler IsBrowserInitializedChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default size of the control.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default <see cref="T:System.Drawing.Size" /> of the control.
|
||||
/// </value>
|
||||
protected override Size DefaultSize
|
||||
{
|
||||
get { return new Size(200, 100); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes certain keys as Input keys when CefSettings.MultiThreadedMessageLoop = false
|
||||
/// </summary>
|
||||
/// <param name="keyData">key data</param>
|
||||
/// <returns>true for a select list of keys otherwise defers to base.IsInputKey</returns>
|
||||
protected override bool IsInputKey(Keys keyData)
|
||||
{
|
||||
//This code block is only called/required when CEF is running in the
|
||||
//same message loop as the WinForms UI (CefSettings.MultiThreadedMessageLoop = false)
|
||||
//Without this code, arrows and tab won't be processed
|
||||
switch (keyData)
|
||||
{
|
||||
case Keys.Right:
|
||||
case Keys.Left:
|
||||
case Keys.Up:
|
||||
case Keys.Down:
|
||||
case Keys.Tab:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
case Keys.Shift | Keys.Tab:
|
||||
case Keys.Shift | Keys.Right:
|
||||
case Keys.Shift | Keys.Left:
|
||||
case Keys.Shift | Keys.Up:
|
||||
case Keys.Shift | Keys.Down:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return base.IsInputKey(keyData);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="E:System.Windows.Forms.Control.SizeChanged" /> event.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param>
|
||||
protected override void OnSizeChanged(EventArgs e)
|
||||
{
|
||||
ResizeBrowser(Width, Height);
|
||||
|
||||
base.OnSizeChanged(e);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnVisibleChanged(EventArgs e)
|
||||
{
|
||||
if (Visible)
|
||||
{
|
||||
ShowInternal();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideInternal();
|
||||
}
|
||||
|
||||
base.OnVisibleChanged(e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes the browser to the specified <paramref name="width"/> and <paramref name="height"/>.
|
||||
/// If <paramref name="width"/> and <paramref name="height"/> are both 0 then the browser
|
||||
/// will be hidden and resource usage will be minimised.
|
||||
/// </summary>
|
||||
/// <param name="width">width</param>
|
||||
/// <param name="height">height</param>
|
||||
protected virtual void ResizeBrowser(int width, int height)
|
||||
{
|
||||
if (BrowserHwnd != IntPtr.Zero)
|
||||
{
|
||||
SetWindowPosition(BrowserHwnd, 0, 0, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When minimized set the browser window size to 0x0 to reduce resource usage.
|
||||
/// https://github.com/chromiumembedded/cef/blob/c7701b8a6168f105f2c2d6b239ce3958da3e3f13/tests/cefclient/browser/browser_window_std_win.cc#L87
|
||||
/// </summary>
|
||||
internal virtual void HideInternal()
|
||||
{
|
||||
if (BrowserHwnd != IntPtr.Zero)
|
||||
{
|
||||
SetWindowPosition(BrowserHwnd, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the browser (called after previous minimised)
|
||||
/// </summary>
|
||||
internal virtual void ShowInternal()
|
||||
{
|
||||
if (BrowserHwnd != IntPtr.Zero)
|
||||
{
|
||||
SetWindowPosition(BrowserHwnd, 0, 0, Width, Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
BrowserHwnd = IntPtr.Zero;
|
||||
IsBrowserInitializedChanged = null;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trigger the <see cref="IsBrowserInitializedChanged"/> event
|
||||
/// </summary>
|
||||
internal void RaiseIsBrowserInitializedChangedEvent()
|
||||
{
|
||||
IsBrowserInitializedChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void SetWindowPosition(IntPtr handle, int x, int y, int width, int height)
|
||||
{
|
||||
const uint SWP_NOMOVE = 0x0002;
|
||||
const uint SWP_NOZORDER = 0x0004;
|
||||
const uint SWP_NOACTIVATE = 0x0010;
|
||||
|
||||
if (handle != IntPtr.Zero)
|
||||
{
|
||||
if (width == 0 && height == 0)
|
||||
{
|
||||
// For windowed browsers when the frame window is minimized set the
|
||||
// browser window size to 0x0 to reduce resource usage.
|
||||
SetWindowPos(handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowPos(handle, IntPtr.Zero, x, y, width, height, SWP_NOZORDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ChromiumHostControl"/> or <see cref="ChromiumWebBrowser"/> associated with
|
||||
/// a specific <see cref="IBrowser"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="browser">browser</param>
|
||||
/// <returns>returns the assocaited <see cref="ChromiumHostControl"/> or <see cref="ChromiumWebBrowser"/> or null if Disposed or no host found.</returns>
|
||||
public static T FromBrowser<T>(IBrowser browser) where T : ChromiumHostControlBase
|
||||
{
|
||||
if (browser.IsDisposed)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var windowHandle = browser.GetHost().GetWindowHandle();
|
||||
|
||||
if (windowHandle == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var control = Control.FromChildHandle(windowHandle) as T;
|
||||
|
||||
return control;
|
||||
}
|
||||
}
|
||||
}
|
42
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/IWinFormsChromiumWebBrowser.cs
vendored
Normal file
42
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/IWinFormsChromiumWebBrowser.cs
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright © 2022 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 CefSharp.WinForms.Host;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CefSharp.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// Winforms Specific Chromium browser implementation, differs from <see cref="IWinFormsWebBrowser"/> in that
|
||||
/// this interface is implemented by both <see cref="ChromiumWebBrowser"/> and <see cref="ChromiumHostControl"/>
|
||||
/// where <see cref="IWinFormsWebBrowser"/> is only implemented by <see cref="ChromiumWebBrowser"/>
|
||||
/// </summary>
|
||||
public interface IWinFormsChromiumWebBrowser : IChromiumWebBrowserBase, IWin32Window, IComponent, ISynchronizeInvoke
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when the browser title changed.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
event EventHandler<TitleChangedEventArgs> TitleChanged;
|
||||
/// <summary>
|
||||
/// Occurs when the browser address changed.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
event EventHandler<AddressChangedEventArgs> AddressChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Event called after the underlying CEF browser instance has been created.
|
||||
/// 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
|
||||
/// thread. It is unwise to block on this thread for any length of time as your browser will become unresponsive and/or hang..
|
||||
/// To access UI elements you'll need to Invoke/Dispatch onto the UI Thread.
|
||||
/// </summary>
|
||||
event EventHandler IsBrowserInitializedChanged;
|
||||
}
|
||||
}
|
16
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/IWinFormsWebBrowser.cs
vendored
Normal file
16
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/IWinFormsWebBrowser.cs
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright © 2014 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.
|
||||
|
||||
namespace CefSharp.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// WinForms specific implementation, has events the
|
||||
/// <see cref="ChromiumWebBrowser" /> implementation exposes.
|
||||
/// </summary>
|
||||
/// <seealso cref="IWebBrowser" /> and <seealso cref="IChromiumWebBrowserBase"/>
|
||||
public interface IWinFormsWebBrowser : IWebBrowser, IWinFormsChromiumWebBrowser
|
||||
{
|
||||
|
||||
}
|
||||
}
|
145
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/ControlExtensions.cs
vendored
Normal file
145
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/ControlExtensions.cs
vendored
Normal file
|
@ -0,0 +1,145 @@
|
|||
// Copyright © 2015 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;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace CefSharp.WinForms.Internals
|
||||
{
|
||||
/// <summary>
|
||||
/// ControlExtensions.
|
||||
/// </summary>
|
||||
public static class ControlExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
|
||||
/// No action will be performed if the control doesn't have a valid handle or the control is Disposed/Disposing.
|
||||
/// </summary>
|
||||
/// <param name="control">the control for which the update is required</param>
|
||||
/// <param name="action">action to be performed on the control</param>
|
||||
internal static void InvokeOnUiThreadIfRequired(this Control control, Action action)
|
||||
{
|
||||
//No action
|
||||
if (control.Disposing || control.IsDisposed || !control.IsHandleCreated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (control.InvokeRequired)
|
||||
{
|
||||
control.BeginInvoke((Action)(() =>
|
||||
{
|
||||
//No action
|
||||
if (control.Disposing || control.IsDisposed || !control.IsHandleCreated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
action();
|
||||
}));
|
||||
}
|
||||
else
|
||||
{
|
||||
action.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes the Action sync on the UI thread, blocks execution on the calling thread.
|
||||
/// No action will be performed if the control doesn't have a valid handle or the control is Disposed/Disposing.
|
||||
/// </summary>
|
||||
/// <param name="control">the control for which the update is required</param>
|
||||
/// <param name="action">action to be performed on the control</param>
|
||||
internal static void InvokeSyncOnUiThreadIfRequired(this Control control, Action action)
|
||||
{
|
||||
//No action
|
||||
if (control.Disposing || control.IsDisposed || !control.IsHandleCreated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (control.InvokeRequired)
|
||||
{
|
||||
control.Invoke(action);
|
||||
}
|
||||
else
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activates the specified control.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
|
||||
public static bool Activate(this Control control)
|
||||
{
|
||||
// Notify WinForms world that inner browser window got focus. This will trigger Leave event to previous focused control
|
||||
var containerControl = control.GetContainerControl();
|
||||
if (containerControl != null)
|
||||
{
|
||||
return containerControl.ActivateControl(control);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the supplied control is the currently
|
||||
/// active control.
|
||||
/// </summary>
|
||||
/// <param name="control">the control to check</param>
|
||||
/// <returns>true if the control is the currently active control</returns>
|
||||
public static bool IsActiveControl(this Control control)
|
||||
{
|
||||
Form form = control.FindForm();
|
||||
if (form == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Control activeControl = form.ActiveControl;
|
||||
while (activeControl != null
|
||||
&& (activeControl is ContainerControl)
|
||||
&& !Object.ReferenceEquals(control, activeControl))
|
||||
{
|
||||
var containerControl = activeControl as ContainerControl;
|
||||
activeControl = containerControl.ActiveControl;
|
||||
}
|
||||
return Object.ReferenceEquals(control, activeControl);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the next control.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
/// <param name="next">if set to <c>true</c> [next].</param>
|
||||
public static void SelectNextControl(this Control control, bool next)
|
||||
{
|
||||
var containerControl = control.GetContainerControl();
|
||||
|
||||
while (containerControl != null)
|
||||
{
|
||||
var containerControlAsControl = containerControl as Control;
|
||||
if (containerControlAsControl == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var activeControl = containerControl.ActiveControl;
|
||||
if (containerControlAsControl.SelectNextControl(activeControl, next, true, true, false))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (containerControlAsControl.Parent == null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
containerControl = containerControlAsControl.Parent.GetContainerControl();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
122
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/DefaultFocusHandler.cs
vendored
Normal file
122
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/DefaultFocusHandler.cs
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
// Copyright © 2014 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.
|
||||
|
||||
namespace CefSharp.WinForms.Internals
|
||||
{
|
||||
/// <summary>
|
||||
/// Default implementation of <see cref="IFocusHandler" />
|
||||
/// for the WinForms implementation
|
||||
/// </summary>
|
||||
/// <seealso cref="CefSharp.IFocusHandler" />
|
||||
public class DefaultFocusHandler : IFocusHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when the browser component has received focus.
|
||||
/// </summary>
|
||||
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control</param>
|
||||
/// <param name="browser">the browser object</param>
|
||||
/// <remarks>Try to avoid needing to override this logic in a subclass. The implementation in
|
||||
/// DefaultFocusHandler relies on very detailed behavior of how WinForms and
|
||||
/// Windows interact during window activation.</remarks>
|
||||
public virtual void OnGotFocus(IWebBrowser chromiumWebBrowser, IBrowser browser)
|
||||
{
|
||||
//We don't deal with popups as they're rendered by default entirely by CEF
|
||||
//For print dialogs the browser will be null, we don't want to deal with that either.
|
||||
if (browser == null || browser.IsPopup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var winFormsChromiumWebBrowser = (ChromiumWebBrowser)chromiumWebBrowser;
|
||||
// During application activation, CEF receives a WM_SETFOCUS
|
||||
// message from Windows because it is the top window
|
||||
// on the CEF UI thread.
|
||||
//
|
||||
// If the WinForm ChromiumWebBrowser control is the
|
||||
// current .ActiveControl before app activation
|
||||
// then we MUST NOT try to reactivate the WinForm
|
||||
// control during activation because that will
|
||||
// start a race condition between reactivating
|
||||
// the CEF control AND having another control
|
||||
// that should be the new .ActiveControl.
|
||||
//
|
||||
// For example:
|
||||
// * CEF control has focus, and thus ChromiumWebBrowser
|
||||
// is the current .ActiveControl
|
||||
// * Alt-Tab to another application
|
||||
// * Click a non CEF control in the WinForms application.
|
||||
// * This begins the Windows activation process.
|
||||
// * The WM_ACTIVATE process on the WinForm UI thread
|
||||
// will update .ActiveControl to the clicked control.
|
||||
// The clicked control will receive WM_SETFOCUS as well.
|
||||
// (i.e. OnGotFocus)
|
||||
// If the ChromiumWebBrowser was the previous .ActiveControl,
|
||||
// then we set .Activating = true.
|
||||
// * The WM_ACTIVATE process on the CEF thread will
|
||||
// send WM_SETFOCUS to CEF thus staring the race of
|
||||
// which will end first, the WndProc WM_ACTIVATE process
|
||||
// on the WinForm UI thread or the WM_ACTIVATE process
|
||||
// on the CEF UI thread.
|
||||
// * CEF will then call this method on the CEF UI thread
|
||||
// due to WM_SETFOCUS.
|
||||
// * This method will clear the activation state (if any)
|
||||
// on the ChromiumWebBrowser control, due to the race
|
||||
// condition the WinForm UI thread cannot.
|
||||
if (winFormsChromiumWebBrowser.IsActivating)
|
||||
{
|
||||
winFormsChromiumWebBrowser.IsActivating = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, we're not being activated
|
||||
// so we must activate the ChromiumWebBrowser control
|
||||
// for WinForms focus tracking.
|
||||
winFormsChromiumWebBrowser.InvokeOnUiThreadIfRequired(() =>
|
||||
{
|
||||
winFormsChromiumWebBrowser.Activate();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the browser component is requesting focus.
|
||||
/// </summary>
|
||||
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control</param>
|
||||
/// <param name="browser">the browser object</param>
|
||||
/// <param name="source">Indicates where the focus request is originating from.</param>
|
||||
/// <returns>Return false to allow the focus to be set or true to cancel setting the focus.</returns>
|
||||
public virtual bool OnSetFocus(IWebBrowser chromiumWebBrowser, IBrowser browser, CefFocusSource source)
|
||||
{
|
||||
//We don't deal with popups as they're rendered by default entirely by CEF
|
||||
if (browser.IsPopup)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Do not let the browser take focus when a Load method has been called
|
||||
return source == CefFocusSource.FocusSourceNavigation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the browser component is about to lose focus.
|
||||
/// For instance, if focus was on the last HTML element and the user pressed the TAB key.
|
||||
/// </summary>
|
||||
/// <param name="chromiumWebBrowser">the ChromiumWebBrowser control</param>
|
||||
/// <param name="browser">the browser object</param>
|
||||
/// <param name="next">Will be true if the browser is giving focus to the next component
|
||||
/// and false if the browser is giving focus to the previous component.</param>
|
||||
public virtual void OnTakeFocus(IWebBrowser chromiumWebBrowser, IBrowser browser, bool next)
|
||||
{
|
||||
//We don't deal with popups as they're rendered by default entirely by CEF
|
||||
if (browser.IsPopup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var winFormsChromiumWebBrowser = (ChromiumWebBrowser)chromiumWebBrowser;
|
||||
|
||||
// NOTE: OnTakeFocus means leaving focus / not taking focus
|
||||
winFormsChromiumWebBrowser.InvokeOnUiThreadIfRequired(() => winFormsChromiumWebBrowser.SelectNextControl(next));
|
||||
}
|
||||
}
|
||||
}
|
25
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/NativeMethods.cs
vendored
Normal file
25
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/NativeMethods.cs
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright © 2015 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.
|
||||
|
||||
namespace CefSharp.WinForms.Internals
|
||||
{
|
||||
/// <summary>
|
||||
/// Class NativeMethods.
|
||||
/// </summary>
|
||||
internal static class NativeMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// The w m_ move
|
||||
/// </summary>
|
||||
public const int WM_MOVE = 0x3;
|
||||
/// <summary>
|
||||
/// The w m_ moving
|
||||
/// </summary>
|
||||
public const int WM_MOVING = 0x216;
|
||||
/// <summary>
|
||||
/// The w m_ activate
|
||||
/// </summary>
|
||||
public const int WM_ACTIVATE = 0x6;
|
||||
}
|
||||
}
|
350
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/ParentFormMessageInterceptor.cs
vendored
Normal file
350
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Internals/ParentFormMessageInterceptor.cs
vendored
Normal file
|
@ -0,0 +1,350 @@
|
|||
// Copyright © 2015 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;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
using CefSharp.Internals;
|
||||
using CefSharp.WinForms.Host;
|
||||
|
||||
namespace CefSharp.WinForms.Internals
|
||||
{
|
||||
/// <summary>
|
||||
/// ParentFormMessageInterceptor - hooks into the parent forms
|
||||
/// message loop to incercept messages like WM_MOVE
|
||||
/// </summary>
|
||||
/// <seealso cref="System.Windows.Forms.NativeWindow" />
|
||||
/// <seealso cref="System.IDisposable" />
|
||||
public class ParentFormMessageInterceptor : NativeWindow, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Keep track of whether a move is in progress.
|
||||
/// </summary>
|
||||
private bool isMoving;
|
||||
|
||||
/// <summary>
|
||||
/// Used to determine the coordinates involved in the move
|
||||
/// </summary>
|
||||
private Rectangle movingRectangle;
|
||||
|
||||
/// <summary>
|
||||
/// Store the previous window state, used to determine if the
|
||||
/// Windows was previously <see cref="FormWindowState.Minimized"/>
|
||||
/// and resume rendering
|
||||
/// </summary>
|
||||
private FormWindowState previousWindowState;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the browser.
|
||||
/// </summary>
|
||||
/// <value>The browser.</value>
|
||||
private ChromiumHostControlBase Browser { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parent form.
|
||||
/// </summary>
|
||||
/// <value>The parent form.</value>
|
||||
private Form ParentForm { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Called when the parent form is moving
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> Moving;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ParentFormMessageInterceptor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="browser">The browser.</param>
|
||||
public ParentFormMessageInterceptor(ChromiumHostControlBase 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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Call to force refinding of the parent Form.
|
||||
/// (i.e. top level window that owns the ChromiumWebBrowserControl)
|
||||
/// </summary>
|
||||
public void RefindParentForm()
|
||||
{
|
||||
ParentParentChanged(Browser, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjust the form to listen to if the ChromiumWebBrowserControl's parent changes.
|
||||
/// </summary>
|
||||
/// <param name="sender">The ChromiumWebBrowser whose parent has changed.</param>
|
||||
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
||||
private void ParentParentChanged(object sender, EventArgs e)
|
||||
{
|
||||
var control = (Control)sender;
|
||||
var oldForm = ParentForm;
|
||||
var newForm = control.FindForm();
|
||||
|
||||
if (oldForm == null || newForm == null || oldForm.Handle != newForm.Handle)
|
||||
{
|
||||
if (Handle != IntPtr.Zero)
|
||||
{
|
||||
ReleaseHandle();
|
||||
}
|
||||
if (oldForm != null)
|
||||
{
|
||||
oldForm.HandleCreated -= OnHandleCreated;
|
||||
oldForm.HandleDestroyed -= OnHandleDestroyed;
|
||||
oldForm.Resize -= OnResize;
|
||||
}
|
||||
ParentForm = newForm;
|
||||
if (newForm != null)
|
||||
{
|
||||
newForm.HandleCreated += OnHandleCreated;
|
||||
newForm.HandleDestroyed += OnHandleDestroyed;
|
||||
newForm.Resize += OnResize;
|
||||
|
||||
previousWindowState = newForm.WindowState;
|
||||
|
||||
// If newForm's Handle has been created already,
|
||||
// our event listener won't be called, so call it now.
|
||||
if (newForm.IsHandleCreated)
|
||||
{
|
||||
OnHandleCreated(newForm, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnResize(object sender, EventArgs e)
|
||||
{
|
||||
var form = (Form)sender;
|
||||
|
||||
if (previousWindowState == form.WindowState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (form.WindowState)
|
||||
{
|
||||
case FormWindowState.Normal:
|
||||
case FormWindowState.Maximized:
|
||||
{
|
||||
if (previousWindowState == FormWindowState.Minimized)
|
||||
{
|
||||
Browser?.ShowInternal();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormWindowState.Minimized:
|
||||
{
|
||||
Browser?.HideInternal();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
previousWindowState = form.WindowState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:HandleCreated" /> event.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
|
||||
private void OnHandleCreated(object sender, EventArgs e)
|
||||
{
|
||||
AssignHandle(((Form)sender).Handle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:HandleDestroyed" /> event.
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
|
||||
private void OnHandleDestroyed(object sender, EventArgs e)
|
||||
{
|
||||
ReleaseHandle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the default window procedure associated with this window.
|
||||
/// </summary>
|
||||
/// <param name="m">A <see cref="T:System.Windows.Forms.Message" /> that is associated with the current Windows message.</param>
|
||||
protected override void WndProc(ref Message m)
|
||||
{
|
||||
var isMovingMessage = false;
|
||||
|
||||
// Negative initial values keeps the compiler quiet and to
|
||||
// ensure we have actual window movement to notify CEF about.
|
||||
const int invalidMoveCoordinate = -1;
|
||||
var x = invalidMoveCoordinate;
|
||||
var y = invalidMoveCoordinate;
|
||||
|
||||
// Listen for operating system messages
|
||||
switch (m.Msg)
|
||||
{
|
||||
case NativeMethods.WM_ACTIVATE:
|
||||
{
|
||||
// Intercept (de)activate messages for our form so that we can
|
||||
// ensure that we play nicely with WinForms .ActiveControl
|
||||
// tracking.
|
||||
var browser = Browser;
|
||||
if ((int)m.WParam == 0x0) // WA_INACTIVE
|
||||
{
|
||||
// If the CEF browser no longer has focus,
|
||||
// we won't get a call to OnLostFocus on ChromiumWebBrowser.
|
||||
// However, it doesn't matter so much since the CEF
|
||||
// browser will receive it instead.
|
||||
|
||||
// Paranoia about making sure the IsActivating state is correct now.
|
||||
browser.IsActivating = false;
|
||||
DefWndProc(ref m);
|
||||
}
|
||||
else // WA_ACTIVE or WA_CLICKACTIVE
|
||||
{
|
||||
// Only set IsActivating if the ChromiumWebBrowser was the form's
|
||||
// ActiveControl before the last deactivation.
|
||||
browser.IsActivating = browser.IsActiveControl();
|
||||
DefWndProc(ref m);
|
||||
// During activation, WM_SETFOCUS gets sent to
|
||||
// to the CEF control since it's the root window
|
||||
// of the CEF UI thread.
|
||||
//
|
||||
// Therefore, don't set .IsActivating to false here
|
||||
// instead do so in DefaultFocusHandler.OnGotFocus.
|
||||
// Otherwise there's a race condition between this
|
||||
// thread setting activating to false and
|
||||
// the CEF DefaultFocusHandler executing to determine
|
||||
// it shouldn't Activate() the control.
|
||||
}
|
||||
return;
|
||||
}
|
||||
case NativeMethods.WM_MOVING:
|
||||
{
|
||||
movingRectangle = (Rectangle)Marshal.PtrToStructure(m.LParam, typeof(Rectangle));
|
||||
x = movingRectangle.Left;
|
||||
y = movingRectangle.Top;
|
||||
isMovingMessage = true;
|
||||
break;
|
||||
}
|
||||
case NativeMethods.WM_MOVE:
|
||||
{
|
||||
// Convert IntPtr into 32bit int safely without
|
||||
// exceptions:
|
||||
int dwLParam = m.LParam.CastToInt32();
|
||||
|
||||
// Extract coordinates from lo/hi word:
|
||||
x = dwLParam & 0xffff;
|
||||
y = (dwLParam >> 16) & 0xffff;
|
||||
|
||||
isMovingMessage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Only notify about movement if:
|
||||
// * Browser Handle Created
|
||||
// NOTE: This is checked for paranoia.
|
||||
// This WndProc can't be called unless ParentForm has
|
||||
// its handle created, but that doesn't necessarily mean
|
||||
// Browser has had its handle created.
|
||||
// WinForm controls don't usually get eagerly created Handles
|
||||
// in their constructors.
|
||||
// * ParentForm Actually moved
|
||||
// * Not currently moving (on the UI thread only of course)
|
||||
// * The current WindowState is Normal.
|
||||
// This check is to simplify the effort here.
|
||||
// Other logic already handles the maximize/minimize
|
||||
// cases just fine.
|
||||
// You might consider checking Browser.Visible and
|
||||
// not notifying our browser control if the browser control isn't visible.
|
||||
// However, if you do that, the non-Visible CEF tab will still
|
||||
// have any SELECT drop downs rendering where they shouldn't.
|
||||
if (isMovingMessage
|
||||
&& Browser.IsHandleCreated
|
||||
&& ParentForm.WindowState == FormWindowState.Normal
|
||||
&& (ParentForm.Left != x || ParentForm.Top != y)
|
||||
&& !isMoving)
|
||||
{
|
||||
// ParentForm.Left & .Right are negative when the window
|
||||
// is transitioning from maximized to normal.
|
||||
// If we are transitioning, the form will also receive
|
||||
// a WM_SIZE which can deal with the move/size combo itself.
|
||||
if (ParentForm.Left >= 0 && ParentForm.Right >= 0)
|
||||
{
|
||||
OnMoving();
|
||||
}
|
||||
}
|
||||
DefWndProc(ref m);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when [moving].
|
||||
/// </summary>
|
||||
protected virtual void OnMoving()
|
||||
{
|
||||
isMoving = true;
|
||||
|
||||
Moving?.Invoke(Browser, EventArgs.Empty);
|
||||
|
||||
isMoving = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and - optionally - managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
Moving = null;
|
||||
|
||||
if (ParentForm != null)
|
||||
{
|
||||
ParentForm.HandleCreated -= OnHandleCreated;
|
||||
ParentForm.HandleDestroyed -= OnHandleDestroyed;
|
||||
ParentForm.Resize -= OnResize;
|
||||
ParentForm = null;
|
||||
}
|
||||
|
||||
// Unmanaged resource, but release here anyway.
|
||||
// NativeWindow has its own finalization logic
|
||||
// that should be run if this instance isn't disposed
|
||||
// properly before arriving at the finalization thread.
|
||||
// See: http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/NativeWindow.cs,147
|
||||
// for the gruesome details.
|
||||
if (Handle != IntPtr.Zero)
|
||||
{
|
||||
ReleaseHandle();
|
||||
}
|
||||
|
||||
if (Browser != null)
|
||||
{
|
||||
Browser.ParentChanged -= ParentParentChanged;
|
||||
Browser = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, manages an unhandled thread exception.
|
||||
/// </summary>
|
||||
/// <param name="e">An <see cref="T:System.Exception" /> that specifies the unhandled thread exception.</param>
|
||||
protected override void OnThreadException(Exception e)
|
||||
{
|
||||
// TODO: Do something more interesting here, logging, whatever, something.
|
||||
base.OnThreadException(e);
|
||||
}
|
||||
}
|
||||
}
|
18
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Properties/AssemblyInfo.cs
vendored
Normal file
18
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/Properties/AssemblyInfo.cs
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using CefSharp;
|
||||
|
||||
[assembly: AssemblyTitle("CefSharp.WinForm")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: AssemblyCompany(AssemblyInfo.AssemblyCompany)]
|
||||
[assembly: AssemblyProduct(AssemblyInfo.AssemblyProduct)]
|
||||
[assembly: AssemblyCopyright(AssemblyInfo.AssemblyCopyright)]
|
||||
[assembly: ComVisible(AssemblyInfo.ComVisible)]
|
||||
[assembly: AssemblyVersion(AssemblyInfo.AssemblyVersion)]
|
||||
[assembly: AssemblyFileVersion(AssemblyInfo.AssemblyFileVersion)]
|
||||
[assembly: CLSCompliant(AssemblyInfo.ClsCompliant)]
|
136
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/WebBrowserExtensions.cs
vendored
Normal file
136
packages/CefSharp.WinForms.113.1.40/src/CefSharp.WinForms/WebBrowserExtensions.cs
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
// 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;
|
||||
using System.Windows.Forms;
|
||||
using CefSharp.WinForms.Host;
|
||||
|
||||
namespace CefSharp.WinForms
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper extensions for performing common CefSharp related WinForms tasks
|
||||
/// </summary>
|
||||
public static class WebBrowserExtensions
|
||||
{
|
||||
[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>
|
||||
/// <param name="chromiumWebBrowser">the <see cref="ChromiumWebBrowser"/> or <see cref="ChromiumHostControl"/> instance.</param>
|
||||
/// <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>
|
||||
public static bool DestroyWindow(this IChromiumWebBrowserBase chromiumWebBrowser)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
var browser = chromiumWebBrowser.BrowserCore;
|
||||
|
||||
if (browser == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var handle = browser.GetHost().GetWindowHandle();
|
||||
|
||||
|
||||
return DestroyWindow(handle);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// <param name="controlName">Control name</param>
|
||||
/// <param name="dockStyle">Dock Style</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, Control parentControl, string controlName = nameof(ChromiumHostControl) + "DevTools", DockStyle dockStyle = DockStyle.Fill, int inspectElementAtX = 0, int inspectElementAtY = 0)
|
||||
{
|
||||
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>
|
||||
/// <param name="controlName">control name</param>
|
||||
/// <param name="dockStyle">Dock Style</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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5.2", FrameworkDisplayName = ".NET Framework 4.5.2")]
|
|
@ -0,0 +1,4 @@
|
|||
// <autogenerated />
|
||||
using System;
|
||||
using System.Reflection;
|
||||
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
|
Reference in a new issue