今天开始继续Avalonia练习。
本节:CefNet
1.引入
CefNet.Avalonia.Eleven
2.项目引入
Program中加入
using Avalonia;
using Avalonia.ReactiveUI;
using Avalonia.Threading;
using CefNet;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace CefAvalonia
{
internal sealed class Program
{
internal static CefAppImpl? app;
private static DispatcherTimer? messagePump;
private const int messagePumpDelay = 10;
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args)
{
string cefPath = GetProjectPath(PlatformInfo.IsMacOS);
bool externalMessagePump = args.Contains("--external-message-pump");
if (PlatformInfo.IsMacOS)
{
externalMessagePump = true;
}
var settings = new CefSettings();
settings.MultiThreadedMessageLoop = !externalMessagePump;
settings.ExternalMessagePump = externalMessagePump;
settings.NoSandbox = true;
settings.WindowlessRenderingEnabled = true;
settings.LocalesDirPath = Path.Combine(cefPath, PlatformInfo.IsMacOS ? "Resources" : "locales");
settings.ResourcesDirPath = Path.Combine(cefPath, PlatformInfo.IsMacOS ? "Resources" : "");
settings.LogSeverity = CefLogSeverity.Warning;
settings.UncaughtExceptionStackSize = 8;
App.FrameworkInitialized += App_FrameworkInitialized;
App.FrameworkShutdown += App_FrameworkShutdown;
app = new CefAppImpl();
app.ScheduleMessagePumpWorkCallback = OnScheduleMessagePumpWork;
app.Initialize(cefPath, settings);
BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
}
private static string GetProjectPath(bool isMacOS)
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cefnet", "Release", isMacOS ? Path.Combine("cefclient.app", "Contents", "Frameworks", "Chromium Embedded Framework.framework") : "");
}
private static void App_FrameworkInitialized(object? sender, EventArgs e)
{
if (CefNetApplication.Instance.UsesExternalMessageLoop)
{
messagePump = new DispatcherTimer(TimeSpan.FromMilliseconds(messagePumpDelay), DispatcherPriority.Normal, (s, e) =>
{
CefApi.DoMessageLoopWork();
Dispatcher.UIThread.RunJobs();
});
messagePump.Start();
}
}
private static void App_FrameworkShutdown(object? sender, EventArgs e)
{
messagePump?.Stop();
}
private static async void OnScheduleMessagePumpWork(long delayMs)
{
await Task.Delay((int)delayMs);
Dispatcher.UIThread.Post(CefApi.DoMessageLoopWork);
}
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
.UseReactiveUI();
}
}
APP中加入
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using CefAvalonia.ViewModels;
using CefAvalonia.Views;
using System;
namespace CefAvalonia
{
public partial class App : Application
{
public static event EventHandler? FrameworkInitialized;
public static event EventHandler? FrameworkShutdown;
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
}
}
添加一个实现处理类
using CefNet;
using System;
using System.Runtime.InteropServices;
namespace CefAvalonia
{
internal class CefAppImpl:CefNetApplication
{
protected override void OnBeforeCommandLineProcessing(string processType, CefCommandLine commandLine)
{
base.OnBeforeCommandLineProcessing(processType, commandLine);
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
commandLine.AppendSwitch("no-zygote");
commandLine.AppendSwitch("no-sandbox");
}
}
public Action<long> ScheduleMessagePumpWorkCallback { get; set; }
protected override void OnScheduleMessagePumpWork(long delayMs)
{
ScheduleMessagePumpWorkCallback(delayMs);
}
}
}
窗口后台
using Avalonia.Controls;
using CefNet.Avalonia;
namespace CefAvalonia.Views
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
WebView webview = new() { Focusable = true };
Content = webview;
webview.BrowserCreated += (s, e) => webview.Navigate("https://www.baidu.com");
webview.DocumentTitleChanged += (s, e) => Title = e.Title;
Closing += (s, e) => Program.app?.Shutdown();
}
}
}
最后,下载对应的库
CEF Automated Builds (spotifycdn.com)
运行效果