目录

BrowserView

该文档描述了如何在 WinForms、WPF、WinUI 3 和 Avalonia UI 应用程序中嵌入一个显示网页内容的可视化组件。

嵌入 

DotNetBrowser 可用于使用以下 .NET GUI 框架构建的 .NET 应用程序:

  • WinForms
  • WPF
  • WinUI 3
  • Avalonia UI

IBrowser 组件本身并不是一个可用于显示网页的可视化组件。要显示 IBrowser中加载的网页内容,请根据所使用的 GUI 框架,使用以下控件之一:

  • DotNetBrowser.WinForms.BrowserView
  • DotNetBrowser.Wpf.BrowserView
  • DotNetBrowser.WinUi3.BrowserView
  • DotNetBrowser.AvaloniaUi.BrowserView

所有这些控件都实现了 IBrowserView 接口。必要时通过调用 InitializeFrom(IBrowser) 扩展方法建立视图与特定 IBrowser 实例的连接。

从单个浏览器初始化多个视图是不可能的 - 如果一个浏览器视图绑定到该浏览器实例,则该视图将被后续的 InitializeFrom 调用取消初始化。

InitializeFrom(IBrowser) 扩展方法应从 UI 线程调用。

当应用程序关闭时,IBrowserView 实现不会处理已连接的 IBrowser 或 IEngine 实例。因此,即使关闭了所有应用程序窗口,浏览器和引擎也会继续运行,并阻止应用程序终止。要解决这种情况,有必要在应用程序关闭时处理 IBrowser 或 IEngine 实例。

在 WinUI 3 中,关闭最后一个窗口会停止 UI 线程的消息循环,即使引擎仍在创建中也是如此;请参阅 WinUI 3。

WinForms 

要在 .NET WinForms 应用程序中显示网页内容,请创建DotNetBrowser.WinForms.BrowserView 实例:

C#
VB
using DotNetBrowser.WinForms;
// ...
BrowserView browserView = new BrowserView();
browserView.InitializeFrom(browser);
Imports DotNetBrowser.WinForms
' ...
Dim browserView As New BrowserView()
browserView.InitializeFrom(browser)

并将其嵌入 Form中:

C#
VB
form.Controls.Add(view);
form.Controls.Add(view)

下面是完整的示例:

C#
VB

using System.Windows.Forms;
using DotNetBrowser.Browser;
using DotNetBrowser.Engine;
using DotNetBrowser.WinForms;

namespace Embedding.WinForms
{
    /// <summary>
    ///     本例演示如何将 DotNetBrowser
    ///     嵌入到 Windows Forms 应用程序中。
    /// </summary>
    public partial class Form1 : Form
    {
        private const string Url = "https://html5test.teamdev.com/";
        private readonly IBrowser browser;
        private readonly IEngine engine;

        public Form1()
        {
            // 创建 Windows Forms BrowserView 控件。
            BrowserView browserView = new BrowserView
            {
                Dock = DockStyle.Fill
            };

            // 创建并初始化 IEngine 实例。
            EngineOptions engineOptions = new EngineOptions.Builder
            {
                RenderingMode = RenderingMode.HardwareAccelerated
            }.Build();
            engine = EngineFactory.Create(engineOptions);

            // 创建 IBrowser 实例。
            browser = engine.CreateBrowser();

            InitializeComponent();
            
            // 将 BrowserView 控件添加到 Form。
            Controls.Add(browserView);
            FormClosed += Form1_FormClosed;

            // 初始化 Windows Forms BrowserView 控件。
            browserView.InitializeFrom(browser);
            browser.Navigation.LoadUrl(Url);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            browser?.Dispose();
            engine?.Dispose();
        }
    }
}

Imports System.Windows.Forms
Imports DotNetBrowser.Browser
Imports DotNetBrowser.Engine
Imports DotNetBrowser.WinForms

Namespace Embedding.WinForms
    ''' <summary>
    '''     此示例演示如何将 DotNetBrowser 嵌入
    '''     到 Windows Forms 应用程序中。
    ''' </summary>
    Partial Public Class Form1
        Inherits Form

        Private Const Url As String = "https://html5test.teamdev.com/"
        Private ReadOnly browser As IBrowser
        Private ReadOnly engine As IEngine

        Public Sub New()
            ' 创建 Windows Forms BrowserView 控件。
            Dim browserView As New BrowserView With {.Dock = DockStyle.Fill}

            ' 创建和初始化 IEngine 实例。
            Dim engineOptions As EngineOptions = New EngineOptions.Builder With {
                .RenderingMode = RenderingMode.HardwareAccelerated
            }.Build()
            engine = EngineFactory.Create(engineOptions)

            ' 创建 IBrowser 实例。
            browser = engine.CreateBrowser()

            InitializeComponent()

            ' 将 BrowserView 控件添加到 Form 中。
            Controls.Add(browserView)
            AddHandler FormClosed, AddressOf Form1_FormClosed

            ' 初始化 Windows Forms BrowserView 控件。
            browserView.InitializeFrom(browser)
            browser.Navigation.LoadUrl(Url)
        End Sub

        Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs)
            browser?.Dispose()
            engine?.Dispose()
        End Sub
    End Class
End Namespace

该示例的输出如下所示: WinForms View

我们的存储库中提供了完整的项目:C#, VB.

WPF 

要在 WPF 应用程序中显示网页内容,请创建一个 DotNetBrowser.Wpf.BrowserView 实例:

C#
VB
using DotNetBrowser.Wpf;
// ...
BrowserView browserView = new BrowserView();
browserView.InitializeFrom(browser);
Imports DotNetBrowser.Wpf
' ...
Dim browserView As New BrowserView()
browserView.InitializeFrom(browser)

下面是完整的示例:

MainWindow.xaml

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:WPF="clr-namespace:DotNetBrowser.Wpf;assembly=DotNetBrowser.Wpf"
    x:Class="Embedding.Wpf.MainWindow"
    mc:Ignorable="d"
    Title="DotNetBrowser — WPF" Height="480" Width="800" Closed="Window_Closed">
    <Grid>
        <WPF:BrowserView Name="browserView" />
    </Grid>
</Window>
C#
VB

using System;
using System.Windows;
using DotNetBrowser.Browser;
using DotNetBrowser.Engine;

namespace Embedding.Wpf
{
    /// <summary>
    ///     此示例演示如何将 DotNetBrowser 嵌入
    ///     到 WPF 应用程序中。
    /// </summary>
    public partial class MainWindow : Window
    {
        private const string Url = "https://html5test.teamdev.com/";
        private readonly IBrowser browser;
        private readonly IEngine engine;

        public MainWindow()
        {
            // 创建和初始化 IEngine 实例。
            EngineOptions engineOptions = new EngineOptions.Builder
            {
                RenderingMode = RenderingMode.HardwareAccelerated
            }.Build();
            engine = EngineFactory.Create(engineOptions);

            // 创建 IBrowser 实例。
            browser = engine.CreateBrowser();

            InitializeComponent();

            // 初始化 WPF BrowserView 控件。
            browserView.InitializeFrom(browser);
            browser.Navigation.LoadUrl(Url);
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            browser?.Dispose();
            engine?.Dispose();
        }
    }
}

Imports System.Windows
Imports DotNetBrowser.Browser
Imports DotNetBrowser.Engine

Namespace Embedding.Wpf
    ''' <summary>
    '''     此示例演示如何将 DotNetBrowser 嵌入
    '''     到 WPF 应用程序中。
    ''' </summary>
    Partial Public Class MainWindow
        Inherits Window

        Private Const Url As String = "https://html5test.teamdev.com/"
        Private ReadOnly browser As IBrowser
        Private ReadOnly engine As IEngine

        Public Sub New()
            ' 创建和初始化 IEngine 实例。
            Dim engineOptions As EngineOptions = New EngineOptions.Builder With {
                .RenderingMode = RenderingMode.HardwareAccelerated
            }.Build()
            engine = EngineFactory.Create(engineOptions)

            ' 创建 IBrowser 实例。
            browser = engine.CreateBrowser()

            InitializeComponent()

            ' 初始化 WPF BrowserView 控件。
            browserView.InitializeFrom(browser)
            browser.Navigation.LoadUrl(Url)
        End Sub

        Private Sub Window_Closed(sender As Object, e As EventArgs)
            browser?.Dispose()
            engine?.Dispose()
        End Sub
    End Class
End Namespace

该示例的输出如下所示: WPF View

完整的项目在我们的存储库中可用:C#, VB.

ElementHost 

我们建议在 WinForms 应用程序中使用 WinForms BrowserView,在 WPF 应用程序中使用 WPF BrowserView。

有时您需要将 WPF BrowserView 嵌入到 WinForms 应用程序中。例如,当使用 WPF UI 工具包开发复杂的网页浏览器控件时,您必须在 WinForms 应用程序中显示此 WPF 控件。例如,当使用 WPF UI 工具包开发复杂的网页浏览器控件时,您必须在 WinForms 应用程序中显示此 WPF 控件。

从 v.2.0 开始,您可以使用 ElementHost 将 WPF BrowserView 嵌入到 WinForms 窗口中。它支持所有的渲染模式。它支持所有的渲染模式。

C#
VB

using System;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using DotNetBrowser.Browser;
using DotNetBrowser.Engine;
using DotNetBrowser.Wpf;

namespace ElementHostEmbedding.WinForms
{
    public partial class Form1 : Form
    {
        private const string Url = "https://html5test.teamdev.com";
        private readonly IBrowser browser;
        private readonly IEngine engine;
        private readonly ElementHost host;

        public Form1()
        {
            // 创建和初始化 IEngine 实例。
            EngineOptions engineOptions = new EngineOptions.Builder
            {
                RenderingMode = RenderingMode.OffScreen,
                // 以编程方式设置许可证密钥。
                LicenseKey = "your_license_key_goes_here"
            }.Build();
            engine = EngineFactory.Create(engineOptions);

            // 创建 IBrowser 实例。
            browser = engine.CreateBrowser();
            // 创建  WPF BrowserView 控件。
            BrowserView browserView = new BrowserView();
            
            InitializeComponent();
            FormClosed += Form1_FormClosed;

            // 创建和初始化 ElementHost 控件。
            host = new ElementHost
            {
                Dock = DockStyle.Fill,
                Child = browserView
            };
            Controls.Add(host);

            // 初始化 WPF BrowserView 控件。
            browserView.InitializeFrom(browser);
            browser.Navigation.LoadUrl(Url);
        }

        private void Form1_FormClosed(object sender, EventArgs e)
        {
            browser?.Dispose();
            engine?.Dispose();
        }
    }
}

Imports System.Windows.Forms.Integration
Imports DotNetBrowser.Browser
Imports DotNetBrowser.Engine
Imports DotNetBrowser.Wpf

Namespace ElementHostEmbedding.WinForms
    Partial Public Class Form1
        Inherits Form

        Private Const Url As String = "https://html5test.teamdev.com"
        Private ReadOnly browser As IBrowser
        Private ReadOnly engine As IEngine
        Private ReadOnly host As ElementHost

        Public Sub New()
            ' 创建和初始化 IEngine 实例。
            Dim engineOptions As EngineOptions = New EngineOptions.Builder With {
                .RenderingMode = RenderingMode.OffScreen,
                .LicenseKey = "your_license_key_goes_here"
            }.Build()
            engine = EngineFactory.Create(engineOptions)

            ' 创建 IBrowser 实例。
            browser = engine.CreateBrowser()
            ' 创建  WPF BrowserView 控件。
            Dim browserView As New BrowserView()

            InitializeComponent()
            AddHandler FormClosed, AddressOf Form1_FormClosed

            ' 创建和初始化 ElementHost 控件。
            host = New ElementHost With {
                .Dock = DockStyle.Fill,
                .Child = browserView
            }
            Controls.Add(host)

            ' 初始化 WPF BrowserView 控件。
            browserView.InitializeFrom(browser)
            browser.Navigation.LoadUrl(Url)
        End Sub

        Private Sub Form1_FormClosed(sender As Object, e As EventArgs)
            browser?.Dispose()
            engine?.Dispose()
        End Sub
    End Class
End Namespace

完整的示例可以在我们的存储库中找到:C#, VB.

WinUI 3 

要在 WinUI 3 应用程序中显示网页内容,请将 DotNetBrowser.WinUi3.BrowserView 控件添加到窗口中:

<Window
    x:Class="Example.WinUi.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:app="using:DotNetBrowser.WinUi3"
    Closed="Window_Closed">
    <app:BrowserView Name="BrowserView" />
</Window>

将承载该视图的窗口传递给 BrowserView.SetWindow():

InitializeComponent();
BrowserView.SetWindow(this);
BrowserView.InitializeFrom(browser);

与其他框架一样,请在窗口的 Closed 处理程序中处理浏览器和引擎。

在 WinUI 3 中,关闭最后一个窗口会停止应用程序的事件循环。如果窗口使用 EngineFactory.CreateAsync() 创建引擎,而用户在引擎就绪之前关闭了窗口,引擎仍会启动,但本应处理它的代码将不再运行。要让应用程序一直运行到该引擎被处理,请在等待引擎创建之前,在窗口的 UI 线程上将 Application.Current.DispatcherShutdownMode 设置为 DispatcherShutdownMode.OnExplicitShutdown。此属性需要 Windows App SDK 1.5 或更高版本。在此模式下,应用程序不会自行退出。当以下两个条件都满足时,请调用 Application.Current.Exit():窗口已关闭,并且引擎创建已完成,无论成功还是失败:

  • 如果窗口关闭时引擎创建已完成,请在 Closed 处理程序中处理浏览器和引擎(如果已创建),然后调用 Application.Current.Exit()。
  • 如果窗口在引擎创建期间关闭,请在创建完成后调用 Application.Current.Exit():如果创建成功,则处理引擎;如果创建失败,也要退出,例如在 finally 块中。

有关完整项目,请参阅 WinUI 3 快速入门。

Avalonia UI 

要在 Avalonia UI 应用程序中显示网页内容,请创建一个 DotNetBrowser.AvaloniaUi.BrowserView 实例:

C#
VB
using DotNetBrowser.AvaloniaUi;
// ...
BrowserView browserView = new BrowserView();
browserView.InitializeFrom(browser);
Imports DotNetBrowser.AvaloniaUi
' ...
Dim browserView As New BrowserView()
browserView.InitializeFrom(browser)

下面是完整的示例:

MainWindow.axaml

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:app="clr-namespace:DotNetBrowser.AvaloniaUi;assembly=DotNetBrowser.AvaloniaUi"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="Embedding.AvaloniaUi.MainWindow"
        Title="DotNetBrowser — Avalonia" Closed="Window_Closed">
    <app:BrowserView x:Name="BrowserView"/>
</Window>

MainWindow.axaml.cs

using System;
using Avalonia.Controls;
using DotNetBrowser.Browser;
using DotNetBrowser.Engine;

namespace Embedding.AvaloniaUi
{

    /// <summary>
    ///     此示例演示了如何将 DotNetBrowser 嵌入
    ///     到 Avalonia 应用程序中。
    /// </summary>
    public partial class MainWindow : Window
    {
        private const string Url = "https://html5test.teamdev.com/";
        private readonly IBrowser browser;
        private readonly IEngine engine;

        public MainWindow()
        {
            // 创建并初始化 IEngine 实例。
            EngineOptions engineOptions = new EngineOptions.Builder
            {
                //LicenseKey = "your_license_key"
            }.Build();
            engine = EngineFactory.Create(engineOptions);

            // 创建 IBrowser 实例。
            browser = engine.CreateBrowser();

            InitializeComponent();

            // 初始化 Avalonia UI 的 BrowserView 控件。
            BrowserView.InitializeFrom(browser);
            browser.Navigation.LoadUrl(Url);
        }

        private void Window_Closed(object? sender, EventArgs e)
        {
            browser?.Dispose();
            engine?.Dispose();
        }
    }
}

该示例的输出如下所示: Avalonia UI View

完整的项目可在我们的存储库中找到:C#, VB.

在 Windows 上,请保留 DotNetBrowser Avalonia UI 项目模板中包含的 app.manifest 文件以及 <ApplicationManifest>app.manifest</ApplicationManifest> 项目属性。该清单声明了 PerMonitorV2 DPI 感知,因此应用程序从一开始就是每显示器 DPI 感知的。如果您以其他方式创建项目,请将相同的声明添加到其清单中,如设置进程的默认 DPI 感知中所述。如果没有该声明,其他组件可能会先设置不同的 DPI 模式,BrowserView 在启用了显示缩放的显示器上可能会显得模糊或错位。

对于 Avalonia UI 12,请使用 DotNetBrowser.AvaloniaUi.v12 软件包。它的 BrowserView 位于相同的 DotNetBrowser.AvaloniaUi 命名空间中,但位于 DotNetBrowser.AvaloniaUi.v12 程序集中,因此请在 XAML 中将其引用为 clr-namespace:DotNetBrowser.AvaloniaUi;assembly=DotNetBrowser.AvaloniaUi.v12。有关完整项目,请参阅 Avalonia UI 12 快速入门。

渲染 

DotNetBrowser 支持多种渲染模式。在本节中,我们将介绍每种模式的性能和局限性,并根据 .NET 应用程序的类型为您提供选择正确模式的建议。

为引擎设置的渲染模式是该引擎所有浏览器的默认模式。要为某个浏览器使用不同的模式,请将其传递给 IProfile.CreateBrowser(RenderingMode):

C#
VB
IBrowser browser = engine.Profiles.Default.CreateBrowser(RenderingMode.OffScreen);
Dim browser As IBrowser = engine.Profiles.Default.CreateBrowser(RenderingMode.OffScreen)

弹出窗口浏览器会继承其父浏览器的渲染模式。IBrowser.RenderingMode 属性返回浏览器的渲染模式。

硬件加速 

该库使用 Chromium GPU 进程中的 GPU 渲染网页内容,并将其直接显示在表面上。在这种模式下,BrowserView 会创建并嵌入一个本地重量级窗口(表面),库在该窗口上渲染生成的像素。

离屏 

该库使用 Chromium GPU 进程中的 GPU 渲染网页内容,并将像素复制到 .NET 进程内存中分配的离屏缓冲区。在这种模式下,BrowserView 会创建并嵌入一个轻量级组件,该组件从离屏缓冲区读取像素并使用 UI 框架功能显示它们。

限制 

WPF 空域问题 

当启用 HardwareAccelerated 渲染模式时,不建议在 BrowserView 上显示其他 WPF 组件,因为 BrowserView 使用 HwndHost 显示本机 Win32 窗口。因此,它通常会导致众所周知的空域问题。

WPF 分层窗口 

使用 AllowsTransparency 样式配置 WPF Window 会将 WS_EX_LAYERED 窗口样式标志添加到 Windows 上的 WPF 窗口。此标志用于创建分层窗口。分层窗口是一种在屏幕外绘制内容的窗口。如果我们在启用 HardwareAccelerated 渲染模式时将本机窗口嵌入到分层窗口中,那么由于窗口类型冲突,其内容则不会被绘制。

鼠标、键盘、触摸、拖放 

在 OffScreen 渲染模式下,鼠标、键盘和触摸事件在 .NET 端处理并转发给 Chromium 引擎。

目前,在 WPF 和 Avalonia UI 中都提供全触摸和手势支持。在 WinForms 中,这种功能仅限于轻敲和长按,因为 WinForms 本身对触摸的支持有限。

WPF 不支持拖放(DND)功能,以及OffScreen 渲染模式中的 WinForms。