隆重介绍.NET界面组件WinFormedge


经过几个月的爆肝,目前 WinFormedge 项目已经基本可用并已上传至 NuGet 源。同时附带的示例程序也开发完成并随 WinFormedge 源代码一并开源。欢迎各位以 Win10/11 为主要生产环境的 .NET 开发人员安装体验。

项目简介

WinFormedge 是一个基于 Microsoft WebView2 的开源 .NET 库,开发者能够使用 HTML、CSS 和 JavaScript 创建现代化、具有丰富视觉吸力的 WinForms 应用程序。此项目的灵感源于由本人维护的另外一个 .NET WinForm 界面组件 NanUI,与之不同的是 NanUI 基于 Chromium Embedded Framework (CEF) 作为 Web 的渲染引擎,而 WinFormedge 使用了 WebView2 作为渲染引擎,因此 WinFormedge 在目标为 Windows 10/11 的设备上部署时无需打包庞大的 CEF 运行时文件,极大地减少了应用程序分发包的大小。

功能

WinFormedge 的目标是为 .NET 桌面开发人员提供功能强大且使用便捷的界面组件,目标针对 WinForm 框架,因此使用 WinFormedge 界面框架能够在为 WinForm 项目带来全新界面体验的同时也保留了 .NET 的强大功能。

窗体样式

WinFormedge 目前提供了标准窗体样式、无标题栏窗体样式及透明窗体三种类型的窗体:

标准窗体样式

标准窗体样式与 WinForm 的标准窗体相同,支持最小化、最大化、关闭等操作。不同的是,整个客户区将以开发者设计的 Web 页面所覆盖,当然也可以如下图所示直接使用现有的 Web 站点。

无标题栏窗体样式

无标题栏窗体去除了系统标题栏,允许开发者使用整个窗口区域这能为界面的设计带来极大的灵活性。如图所展示的 WinFormedge 示例程序,窗体移除了系统标准标题栏区域,使用整个 HTML 页面来展现软件的界面。

透明窗体样式

透明窗体允许开发者创建完全透明的窗体,适用于需要特殊视觉效果的应用程序。下图所展示的窗体,在 Windows 系统中使用 HTML 模拟了 macOS Yosemite 的窗体风格,因为使用了 WinFormedge 的透明窗体,因此从窗体的圆角效果、投影效果等等都完全使用 HTML 和 CSS 来实现。

通过调整背景的 Alpha 通道也能实现更多酷炫的透明和半透明效果。

背景样式

此外,WinFormege 还内置了多种窗体背景的样式,包括传统的纯色背景、透明背景、类似 Win7 的高斯模糊背景以及 Win11 的 Mica 背景等。开发者可以根据需要选择合适的背景样式,配合 WebView2 的页面设计以实现不同的视觉效果。

交互功能

为了简化 Web 前端与 WinForm 的功能交互,WinFormege 提供了多种内置的命令及 CSS 帮助类以减少开发者的开发难度,这些功能包括:

窗体命令

窗体命令 app-command 属性是 WinFormedge 扩展的 HTML 元素属性,通过在标准的 HTML 元素上添加这个元素属性以方便地实现窗体的最小化、最大化、全屏及关闭操作。

  • app-command=”minimize” – 最小化窗体
  • app-command=”maximize” – 最大化/恢复窗体
  • app-command=”fullscreen” – 全屏/恢复窗体
  • app-command=”close” – 关闭当前窗体

用法其实很简单,在任意 HTML 元素上加上这个属性并配置期望的操作类型即可:

<div app-command="close">关闭</div>

移动无边框窗体

当使用无标题栏或者透明窗体时,WinFormedge 提供了能够帮助窗体实现点击移动的 app-region 属性,这个属性是一个 CSS 的属性,具有两个属性值 drag 和 no-drag,将这个 CSS 属性应用到合适的元素上即可实现对窗体的拖动移动。

如下所示:

<html>
<head>
  <style>
  header{
    app-region:drag;
  }
  </style>
</head>
<body>
<header>My App</header>
<main>
  <h1>Hi~</h1>
  <p>Drag header to move.</p>
</main>
</body>
</html>

HTML 帮助样式

为了简化前端页面开发人员的工作,WinFormedge 会在页面的 HTML 根元素上根据窗体的状态标记上不同的 class 类名:

  • window–activated – 窗体激活状态
  • window–deactived – 窗体未激活状态
  • window–fullscreen – 窗体全屏状态
  • window–maximized – 窗体最大化状态
  • window__titlebar–shown – 当前窗体具有系统默认的标题栏
  • window__titlebar–shown – 当前窗体为没有标题栏的窗体

通过以上帮助样式,设计人员能够为窗体在不同窗体状态时编写对应的 CSS 样式代码。

前端事件

WinFormedge 提供了一些前端事件,允许开发者在窗体状态变化时执行 JavaScript 代码。开发者通过使用 window.addEventListener 方法来绑定这些事件。目前提供对以下事件的监听:

  • windowactivated – 窗体已激活
  • windowdeactivated – 窗体未激活
  • windowstatechange – 窗体状态改变,参数:state:string = “[normal|maximized|minimized|fullscreen]”
  • windowresize – 窗体尺寸改变,参数:x:int, y:int, width:int, height: int
  • windowmove – 窗体位置改变,参数:x:int, y:int, screenX:int, screenY: int

这些事件类型是 CustomEvent,因此需要通过事件参数的 detail 属性访问到具体的熟悉值。

前端对象

WinFormedge 提供了一个全局的 window.hostWindow 对象,允许开发者访问窗体的相关信息和操作。该对象包含以下属性和方法:

  • hostWindow.activated – 获取窗体激活状态
  • hostWindow.hasTitleBar – 获取窗体是否具有标题栏
  • hostWindow.windowState – 获取窗体当前的状态
  • hostWindow.left – 设置或获取窗体左边距
  • hostWindow.top – 设置或获取窗体上边距
  • hostWindow.width – 设置或获取窗体宽度
  • hostWindow.height – 设置或获取窗体高度
  • hostWindow.activate() – 激活当前窗体
  • hostWindow.minimize() – 最小化当前窗体
  • hostWindow.maximize() – 切换最大化/还原当前窗体
  • hostWindow.restore() – 还原当前窗体
  • hostWindow.fullscreen() – 切换全屏化当前窗体(需要指定 AllowFullscreen 属性)
  • hostWindow.toggleFullscreen() – 切换当前窗体的全屏状态
  • hostWindow.close() – 关闭当前窗体

安装和使用

安装

WinFormedge 已在 github 设置了自动化 nuget 发布,您能够从 nuget 找到最新版的 WinFormedge 包。使用 NuGet 包管理器或者任意 NuGet 管理工具在您的项目中搜索并安装WinFormedge即可。

PM> Install-Package WinFormedge

入门

首先您需要使用 Visual Studio 2022 使用默认的项目模板创建一个 .NET 的 Windows 窗体应用程序。

然后根据以下步骤修改和编写应用程序代码:

使用 WinFormedge 应用程序初始化流程替换默认初始化代码

在 program.cs 文件中,您应使用 FormedgeApp 替代 Application 类来初始化 WinForm 应用程序。FormedgeApp 类是用于创建 WinFormedge 应用程序的构建器,提供了配置和运行应用程序的方法。

using WinFormedge;

namespace MinimalExampleApp;

internal static class Program
{
    [STAThread]
    static void Main()
    {
        ApplicationConfiguration.Initialize();

        var app = FormedgeApp.CreateBuilder()
            .UseDevTools()
            .UseWinFormedgeApp<MyFormedgeApp>().Build();

        app.Run();
    }
}

当 FormedgeApp 类创建后,它将自动初始化 WebView2 环境并运行消息循环。

创建 AppStartup 类

AppStartup 类是 WinFormedge 应用程序的入口点,提供了配置应用程序的方法。您可以重写 OnApplicationLaunched 方法以在应用程序启动前执行初始化任务。

您必须实现 OnApplicationStartup 方法来创建应用程序的主窗口。当该方法返回由 StartupSettings 类生成的值时,FormedgeApp 类将创建应用程序主窗口;若方法返回 null,则应用程序将直接关闭。

using WinFormedge;

namespace MinimalExampleApp;

internal class MyFormedgeApp : AppStartup
{
    protected override bool OnApplicationLaunched(string[] args)
    {
        return true;
    }
    protected override AppCreationAction? OnApplicationStartup(StartupSettings options)
    {
        return options.UseMainWindow(new MyWindow());
    }
}

您可以在 OnApplicationStartup 方法中执行一些操作,例如用户登录、用户设置等,以决定使用哪个窗口启动应用程序。此外,如果条件不满足,您还可以通过返回 null 来终止应用程序。

创建 MainWindow 类

MyWindow 类是应用程序的主窗口,继承自 Formedge 类。您可以使用 Formedge 类创建一个带有 WebView2 的窗口。

using WinFormedge;
using Microsoft.Web.WebView2.Core;

namespace MinimalExampleApp;
internal class MyWindow : Formedge
{
    public MyWindow()
    {
        MinimumSize = new Size(960, 480);
        Size = new Size(1280, 800);
        AllowFullScreen = true;

        Load += MyWindow_Load;
        DOMContentLoaded += MyWindow_DOMContentLoaded;

        Url = "https://cn.bing.com";
    }

    private void MyWindow_Load(object? sender, EventArgs e)
    {
        // 窗口和 WebView2 已准备就绪
    }

    private void MyWindow_DOMContentLoaded(object? sender, CoreWebView2DOMContentLoadedEventArgs e)
    {
        // DOM 内容已加载完成
        ExecuteScriptAsync(""""
(()=>{
const headerEl = document.querySelector("#hdr");
headerEl.style.appRegion="drag";
})();
        """");
    }

    protected override WindowSettings ConfigureHostWindowSettings(HostWindowBuilder opts)
    {
        // 配置主窗口设置
        var win = opts.UseDefaultWindow();

        win.ExtendsContentIntoTitleBar = true;
        win.SystemBackdropType = SystemBackdropType.MicaAlt;

        return win;
    }
}

上述代码创建了一个 Formedge 窗口。通过使用 Url 属性,您可以设置窗口的初始 URL。

默认窗口属性可以在构造函数中设置。对于窗口的特殊样式属性,您需要重写 Formedge 类的 ConfigureHostWindowSettings 方法,并使用其 HostWindowBuilder 参数来确定将采用哪种窗口样式,以及配置该窗口具有的特殊样式。例如,在示例代码中,通过使用 HostWindowBuilder 参数的 UseDefaultWindow 方法,您可以指示 Formedge 创建一个默认窗口,并设置其 ExtendsContentIntoTitleBar 属性以实现无边框效果。

当窗口和 WebView2 准备就绪时,会触发 Load 事件。您可以使用此事件执行任何需要 WebView2 控件准备就绪的初始化任务。
当 DOM 内容加载完成并准备就绪时,会触发 DOMContentLoaded 事件。您可以使用此事件执行任何需要 DOM 内容加载完成的任务。如示例所示,您可以使用 ExecuteScriptAsync 方法在 WebView2 控件中执行 JavaScript 代码。示例中的 JavaScript 代码将 header 元素的 appRegion 属性设置为 drag,这允许用户通过点击并拖动这些矩形上的元素来移动窗口。

运行应用程序

项目仓库

Github: https://github.com/XuanchenLin/WinFormedge
Gitee: https://gitee.com/linxuanchen/WinFormedge

目前 WinFormedge 项目已在 Github 和 Gitee 进行托管,并使用 MIT 开源协议开放源代码,欢迎各位 .NET 开发者安装体验。

欢迎到仓库的 Issues 页面发表建议或意见,同时也欢迎任何有意义的 PR。