罗丽 發表於 2025-6-12 02:29:00

隆重介绍.NET界面组件WinFormedge

<p>经过几个月的爆肝,目前 WinFormedge 项目已经基本可用并已上传至 NuGet 源。同时附带的示例程序也开发完成并随 WinFormedge 源代码一并开源。欢迎各位以 Win10/11 为主要生产环境的 .NET 开发人员安装体验。</p>
<h2 id="项目简介">项目简介</h2>
<p>WinFormedge 是一个基于 Microsoft WebView2 的开源 .NET 库,开发者能够使用 HTML、CSS 和 JavaScript 创建现代化、具有丰富视觉吸力的 WinForms 应用程序。此项目的灵感源于由本人维护的另外一个 .NET WinForm 界面组件 NanUI,与之不同的是 NanUI 基于 Chromium Embedded Framework (CEF) 作为 Web 的渲染引擎,而 WinFormedge 使用了 WebView2 作为渲染引擎,因此 WinFormedge 在目标为 Windows 10/11 的设备上部署时无需打包庞大的 CEF 运行时文件,极大地减少了应用程序分发包的大小。</p>
<h2 id="功能">功能</h2>
<p>WinFormedge 的目标是为 .NET 桌面开发人员提供功能强大且使用便捷的界面组件,目标针对 WinForm 框架,因此使用 WinFormedge 界面框架能够在为 WinForm 项目带来全新界面体验的同时也保留了 .NET 的强大功能。</p>
<h3 id="窗体样式">窗体样式</h3>
<p>WinFormedge 目前提供了标准窗体样式、无标题栏窗体样式及透明窗体三种类型的窗体:</p>
<p><strong>标准窗体样式</strong></p>
<p>标准窗体样式与 WinForm 的标准窗体相同,支持最小化、最大化、关闭等操作。不同的是,整个客户区将以开发者设计的 Web 页面所覆盖,当然也可以如下图所示直接使用现有的 Web 站点。</p>
<p><img src="https://img2024.cnblogs.com/blog/352785/202506/352785-20250612021855664-2139391527.png" alt="image" loading="lazy"></p>
<p><strong>无标题栏窗体样式</strong></p>
<p>无标题栏窗体去除了系统标题栏,允许开发者使用整个窗口区域这能为界面的设计带来极大的灵活性。如图所展示的 WinFormedge 示例程序,窗体移除了系统标准标题栏区域,使用整个 HTML 页面来展现软件的界面。</p>
<p><img src="https://img2024.cnblogs.com/blog/352785/202506/352785-20250612021920345-1069497224.png" alt="image" loading="lazy"></p>
<p><strong>透明窗体样式</strong></p>
<p>透明窗体允许开发者创建完全透明的窗体,适用于需要特殊视觉效果的应用程序。下图所展示的窗体,在 Windows 系统中使用 HTML 模拟了 macOS Yosemite 的窗体风格,因为使用了 WinFormedge 的透明窗体,因此从窗体的圆角效果、投影效果等等都完全使用 HTML 和 CSS 来实现。</p>
<p><img src="https://img2024.cnblogs.com/blog/352785/202506/352785-20250612021948068-1350279085.png" alt="image" loading="lazy"></p>
<p>通过调整背景的 Alpha 通道也能实现更多酷炫的透明和半透明效果。</p>
<p><img src="https://img2024.cnblogs.com/blog/352785/202506/352785-20250612022004940-572418227.png" alt="image" loading="lazy"></p>
<h3 id="背景样式">背景样式</h3>
<p>此外,WinFormege 还内置了多种窗体背景的样式,包括传统的纯色背景、透明背景、类似 Win7 的高斯模糊背景以及 Win11 的 Mica 背景等。开发者可以根据需要选择合适的背景样式,配合 WebView2 的页面设计以实现不同的视觉效果。</p>
<p><img src="https://img2024.cnblogs.com/blog/352785/202506/352785-20250612022108560-776576294.png" alt="image" loading="lazy"></p>
<h2 id="交互功能">交互功能</h2>
<p>为了简化 Web 前端与 WinForm 的功能交互,WinFormege 提供了多种内置的命令及 CSS 帮助类以减少开发者的开发难度,这些功能包括:</p>
<h3 id="窗体命令">窗体命令</h3>
<p>窗体命令 app-command 属性是 WinFormedge 扩展的 HTML 元素属性,通过在标准的 HTML 元素上添加这个元素属性以方便地实现窗体的最小化、最大化、全屏及关闭操作。</p>
<ul>
<li>app-command="minimize" - 最小化窗体</li>
<li>app-command="maximize" - 最大化/恢复窗体</li>
<li>app-command="fullscreen" - 全屏/恢复窗体</li>
<li>app-command="close" - 关闭当前窗体</li>
</ul>
<p>用法其实很简单,在任意 HTML 元素上加上这个属性并配置期望的操作类型即可:</p>
<pre><code class="language-html">&lt;div app-command="close"&gt;关闭&lt;/div&gt;
</code></pre>
<h3 id="移动无边框窗体">移动无边框窗体</h3>
<p>当使用无标题栏或者透明窗体时,WinFormedge 提供了能够帮助窗体实现点击移动的 app-region 属性,这个属性是一个 CSS 的属性,具有两个属性值 drag 和 no-drag,将这个 CSS 属性应用到合适的元素上即可实现对窗体的拖动移动。</p>
<p>如下所示:</p>
<pre><code class="language-HTML">&lt;html&gt;
&lt;head&gt;
&lt;style&gt;
header{
    app-region:drag;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;header&gt;My App&lt;/header&gt;
&lt;main&gt;
&lt;h1&gt;Hi~&lt;/h1&gt;
&lt;p&gt;Drag header to move.&lt;/p&gt;
&lt;/main&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h3 id="html-帮助样式">HTML 帮助样式</h3>
<p>为了简化前端页面开发人员的工作,WinFormedge 会在页面的 HTML 根元素上根据窗体的状态标记上不同的 class 类名:</p>
<ul>
<li>window--activated - 窗体激活状态</li>
<li>window--deactived - 窗体未激活状态</li>
<li>window--fullscreen - 窗体全屏状态</li>
<li>window--maximized - 窗体最大化状态</li>
<li>window__titlebar--shown - 当前窗体具有系统默认的标题栏</li>
<li>window__titlebar--shown - 当前窗体为没有标题栏的窗体</li>
</ul>
<p>通过以上帮助样式,设计人员能够为窗体在不同窗体状态时编写对应的 CSS 样式代码。</p>
<h3 id="前端事件">前端事件</h3>
<p>WinFormedge 提供了一些前端事件,允许开发者在窗体状态变化时执行 JavaScript 代码。开发者通过使用 window.addEventListener 方法来绑定这些事件。目前提供对以下事件的监听:</p>
<ul>
<li>windowactivated - 窗体已激活</li>
<li>windowdeactivated - 窗体未激活</li>
<li>windowstatechange - 窗体状态改变,参数:state:string = ""</li>
<li>windowresize - 窗体尺寸改变,参数:x:int, y:int, width:int, height: int</li>
<li>windowmove - 窗体位置改变,参数:x:int, y:int, screenX:int, screenY: int</li>
</ul>
<p>这些事件类型是 CustomEvent,因此需要通过事件参数的 detail 属性访问到具体的熟悉值。</p>
<h3 id="前端对象">前端对象</h3>
<p>WinFormedge 提供了一个全局的 window.hostWindow 对象,允许开发者访问窗体的相关信息和操作。该对象包含以下属性和方法:</p>
<ul>
<li>hostWindow.activated - 获取窗体激活状态</li>
<li>hostWindow.hasTitleBar - 获取窗体是否具有标题栏</li>
<li>hostWindow.windowState - 获取窗体当前的状态</li>
<li>hostWindow.left - 设置或获取窗体左边距</li>
<li>hostWindow.top - 设置或获取窗体上边距</li>
<li>hostWindow.width - 设置或获取窗体宽度</li>
<li>hostWindow.height - 设置或获取窗体高度</li>
<li>hostWindow.activate() - 激活当前窗体</li>
<li>hostWindow.minimize() - 最小化当前窗体</li>
<li>hostWindow.maximize() - 切换最大化/还原当前窗体</li>
<li>hostWindow.restore() - 还原当前窗体</li>
<li>hostWindow.fullscreen() - 切换全屏化当前窗体(需要指定 AllowFullscreen 属性)</li>
<li>hostWindow.toggleFullscreen() - 切换当前窗体的全屏状态</li>
<li>hostWindow.close() - 关闭当前窗体</li>
</ul>
<h2 id="安装和使用">安装和使用</h2>
<h3 id="安装">安装</h3>
<p>WinFormedge 已在 github 设置了自动化 nuget 发布,您能够从 nuget 找到最新版的 WinFormedge 包。使用 NuGet 包管理器或者任意 NuGet 管理工具在您的项目中搜索并安装WinFormedge即可。</p>
<pre><code class="language-bash">PM&gt; Install-Package WinFormedge
</code></pre>
<h3 id="入门">入门</h3>
<p>首先您需要使用 Visual Studio 2022 使用默认的项目模板创建一个 .NET 的 Windows 窗体应用程序。</p>
<p>然后根据以下步骤修改和编写应用程序代码:</p>
<p><strong>使用 WinFormedge 应用程序初始化流程替换默认初始化代码</strong></p>
<p>在 program.cs 文件中,您应使用 FormedgeApp 替代 Application 类来初始化 WinForm 应用程序。FormedgeApp 类是用于创建 WinFormedge 应用程序的构建器,提供了配置和运行应用程序的方法。</p>
<pre><code class="language-CSharp">using WinFormedge;

namespace MinimalExampleApp;

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

      var app = FormedgeApp.CreateBuilder()
            .UseDevTools()
            .UseWinFormedgeApp&lt;MyFormedgeApp&gt;().Build();

      app.Run();
    }
}
</code></pre>
<p>当 FormedgeApp 类创建后,它将自动初始化 WebView2 环境并运行消息循环。</p>
<p><strong>创建 AppStartup 类</strong></p>
<p>AppStartup 类是 WinFormedge 应用程序的入口点,提供了配置应用程序的方法。您可以重写 OnApplicationLaunched 方法以在应用程序启动前执行初始化任务。</p>
<p>您必须实现 OnApplicationStartup 方法来创建应用程序的主窗口。当该方法返回由 StartupSettings 类生成的值时,FormedgeApp 类将创建应用程序主窗口;若方法返回 null,则应用程序将直接关闭。</p>
<pre><code class="language-CSharp">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());
    }
}
</code></pre>
<p>您可以在 OnApplicationStartup 方法中执行一些操作,例如用户登录、用户设置等,以决定使用哪个窗口启动应用程序。此外,如果条件不满足,您还可以通过返回 null 来终止应用程序。</p>
<p><strong>创建 MainWindow 类</strong></p>
<p>MyWindow 类是应用程序的主窗口,继承自 Formedge 类。您可以使用 Formedge 类创建一个带有 WebView2 的窗口。</p>
<pre><code class="language-CSharp">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(""""
(()=&gt;{
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;
    }
}
</code></pre>
<p>上述代码创建了一个 Formedge 窗口。通过使用 Url 属性,您可以设置窗口的初始 URL。</p>
<p>默认窗口属性可以在构造函数中设置。对于窗口的特殊样式属性,您需要重写 Formedge 类的 ConfigureHostWindowSettings 方法,并使用其 HostWindowBuilder 参数来确定将采用哪种窗口样式,以及配置该窗口具有的特殊样式。例如,在示例代码中,通过使用 HostWindowBuilder 参数的 UseDefaultWindow 方法,您可以指示 Formedge 创建一个默认窗口,并设置其 ExtendsContentIntoTitleBar 属性以实现无边框效果。</p>
<p>当窗口和 WebView2 准备就绪时,会触发 Load 事件。您可以使用此事件执行任何需要 WebView2 控件准备就绪的初始化任务。<br>
当 DOM 内容加载完成并准备就绪时,会触发 DOMContentLoaded 事件。您可以使用此事件执行任何需要 DOM 内容加载完成的任务。如示例所示,您可以使用 ExecuteScriptAsync 方法在 WebView2 控件中执行 JavaScript 代码。示例中的 JavaScript 代码将 header 元素的 appRegion 属性设置为 drag,这允许用户通过点击并拖动这些矩形上的元素来移动窗口。</p>
<p><strong>运行应用程序</strong></p>
<p><img src="https://img2024.cnblogs.com/blog/352785/202506/352785-20250612022605993-1945686661.png" alt="image" loading="lazy"></p>
<h2 id="项目仓库">项目仓库</h2>
<p>Github: https://github.com/XuanchenLin/WinFormedge<br>
Gitee: https://gitee.com/linxuanchen/WinFormedge</p>
<p>目前 WinFormedge 项目已在 Github 和 Gitee 进行托管,并使用 MIT 开源协议开放源代码,欢迎各位 .NET 开发者安装体验。</p>
<p>欢迎到仓库的 Issues 页面发表建议或意见,同时也欢迎任何有意义的 PR。</p><br><br>
来源:https://www.cnblogs.com/linxuanchen/p/18924815
頁: [1]
查看完整版本: 隆重介绍.NET界面组件WinFormedge