Awesome Chrome Form UI - 框架设计与基础实现

news2024/11/28 0:59:38

Money is not evil by itself.

Its just paper with perceived value to obtain other things we value in other ways.

If not money what is evil you may ask?

Evil is the unquenchable, obsessive and moral bending desire for more.

Evil is the bottomless,soulless and obsessive compulsive pursuit of some pot of gold at the end of some rainbow which doesnt exist.

Evil is having a price tag for your heart and soul in exchange for financial success at any cost.

Evil is trying to buy happiness, again and again until all of those fake, short lived mirages of emotions are gone.

——《Time》 MKJ

一、ACF UI 简介

是什么?

Awesome Chrome Form UI:简称 ACF UI,基于 CefSharp 库进行插件化封装,它提供接口的默认实现(预设)和常用 Attribute 特性(注解),开发者可以开箱即用,无需过多配置即可使用  Web 技术快速构建一个桌面应用。

应用场景:WinForm 嵌入式浏览器解决方案。

客户端嵌入浏览器的框架很多,首选肯定是 Electron,如果有 Rust 基础,可以考虑使用 Tauri 。在 WinForm 框架上,可以选择 WinFormium(曾用名:NanUI),一个经过了 9 年迭代的框架。

如果你想使用 Vue 等前端技术栈构建 Window 桌面应用,并且使用的是 CefSharp 实现,那么你可以考虑使用 ACF UI。

为什么?

该框架的核心是:通过解耦来简化配置,降低开发难度。类似于 SpringBoot 通过注解实现依赖注入和控制反转等功能,ACF UI 提供 Attribute 实现同样的效果,从而提高应用程序的灵活性和可维护性。

 荔枝 例子:使用 Attribute 

直接使用 CefSharp 导出 DotNet 方法时,除了需要编码 CommonUtil 类,还需要添加 Browser 处理逻辑,

引入 ACF UI 后,导出方法只需要加上  [JavascriptObject] 特性,框架会帮你添加 Browser 处理逻辑,

二、框架主流程 V1.0.0 设计

主流程也非常简单:

  1. 初始化 CEF 配置
  2. 初始化基础窗口
  3. 初始化 Browser 配置
  4. 关闭 CEF

三个初始化阶段的操作相同,都是通过反射机制扫描 Attribute 进行配置初始化,如果没有自定义实现配置则采用预设值。

三、框架主流程 V1.0.0 实现

1、AwesomeChromeFormUI 插件模块

配置目标平台,指定 x86 或者 x64 都可以,

删除框架生成的 Class1.cs ,新增 BaseForm.cs ,

using System.Windows.Forms;

namespace AwesomeChromeFormUI.ChromiumForms
{
    public partial class BaseForm : Form
    {
    }
}

2、引入 CefSharp 库

CefSharp.WinForms.119.1.20

3、ControlExtensions

在 UI 线程上异步执行 Action,

using System;
using System.Windows.Forms;

namespace AwesomeChromeFormUI.CommonExtensions
{
    public static class ControlExtensions
    {
        /// <summary>
        /// Executes the Action asynchronously on the UI thread, does not block execution on the calling thread.
        /// </summary>
        /// <param name="control">the control for which the update is required</param>
        /// <param name="action">action to be performed on the control</param>
        public static void InvokeOnUiThreadIfRequired(this Control control, Action action)
        {
            //If you are planning on using a similar function in your own code then please be sure to
            //have a quick read over https://stackoverflow.com/questions/1874728/avoid-calling-invoke-when-the-control-is-disposed
            //No action
            if (control.Disposing || control.IsDisposed || !control.IsHandleCreated)
            {
                return;
            }

            if (control.InvokeRequired)
            {
                control.BeginInvoke(action);
            }
            else
            {
                action.Invoke();
            }
        }
    }
}

4、ConfigurationAttribute 配置特性

规则:ConfigurationAttribute 所标记的类只能被应用一次,并且只能应用于类的定义上,

using System;

namespace AwesomeChromeFormUI.Attributes
{
    /// <summary>
    /// 自定义 BaseForm 配置注解
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class BaseFormConfigurationAttribute : Attribute
    {

    }
}
using System;

namespace AwesomeChromeFormUI.Attributes
{
    /// <summary>
    /// 自定义 Cef 配置注解
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class CefConfigurationAttribute : Attribute
    {
    }
}
using System;

namespace AwesomeChromeFormUI.Attributes
{
    /// <summary>
    /// 自定义 Browser 配置注解
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class BrowserConfigurationAttribute : Attribute 
    {
    }
}

5、Configuration 配置类封装

规则:提供常见的属性作为字段,并通过无参构造函数为属性赋默认值,

using AwesomeChromeFormUI.Constants;
using System.Drawing;
using System.Windows.Forms;

namespace AwesomeChromeFormUI.Configs
{
    public class BaseFormConfiguration
    {
        /// <summary>
        /// 宽度
        /// </summary>
        public int Width { get; set; }
        /// <summary>
        /// 高度
        /// </summary>
        public int Height { get; set; }
        /// <summary>
        /// 标题文本
        /// </summary>
        public string Text { get; set; }
        /// <summary>
        /// Logo
        /// </summary>
        public Icon Icon { get; set; }
        /// <summary>
        /// 窗口边框样式
        /// </summary>
        public FormBorderStyle FormBorderStyle { get; set; }
        /// <summary>
        /// 启动位置
        /// </summary>
        public FormStartPosition StartPosition { get; set; }
        /// <summary>
        /// 窗口状态
        /// </summary>
        public FormWindowState WindowState { get; set; }

        public BaseFormConfiguration()
        {
            this.Width = BaseFormConstant.DEFAULT_WIDTH;
            this.Height = BaseFormConstant.DEFAULT_HEIGHT;
            this.Text = BaseFormConstant.DEFAULT_TITLE;
            this.Icon = new Icon(BaseFormConstant.DEFAULT_ICON);
            this.StartPosition = FormStartPosition.CenterScreen;
            this.FormBorderStyle = FormBorderStyle.Sizable;
            this.WindowState = FormWindowState.Normal;
        }
    }
}
using CefSharp;
using CefSharp.SchemeHandler;
using CefSharp.WinForms;
using System;
using System.IO;

namespace AwesomeChromeFormUI.Configs
{
    public class CefConfiguration
    {
        /// <summary>
        /// 默认前端文件夹
        /// </summary>
        private string _defaultFrontendFolderPath;

        public CefSettingsBase CefSettings { get; set; }
        public bool PerformDependencyCheck { get; set; }
        public IBrowserProcessHandler BrowserProcessHandler { get; set; }

        public CefConfiguration()
        {
            CreateDefaultFrontendFolderPath();

            // Pseudo code; you probably need more in your CefSettings also.
            var settings = new CefSettings()
            {
        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1341647.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多模态大模型-CogVLm 论文阅读笔记

多模态大模型-CogVLm 论文阅读笔记 COGVLM: VISUAL EXPERT FOR LARGE LANGUAGEMODELS 论文地址 :https://arxiv.org/pdf/2311.03079.pdfcode地址 : https://github.com/THUDM/CogVLM时间 : 2023-11机构 : zhipuai,tsinghua关键词: visual language model效果:&#xff08;2023…

C++面向对象(OOP)编程-C++11新特性详解

C11作为一个重要的版本&#xff0c;引入了很多新的特性&#xff0c;解决了C语言本身很多遗留的内存泄露问题&#xff0c;并且提供了很多比较灵活的用法。引入的auto&#xff0c;智能指针、线程机制都使得C语言的灵活性、安全性、并发性有了很大的提升。 本文会比较详细的介绍C1…

医疗行业的信息安全现状

文章目录 前言一、医疗行业相关政策法规二、“互联网+医疗健康”推进信息安全建设三、医疗行业网络安全形势依然严峻1、等级保护工作未全面开展落实2、医疗行业网络安全风险较高医疗行业网络安全隐患普遍存在遭受勒索病毒攻击严重3、安全防护水平相对落后缺乏必要的网络安全防护…

QT应用篇 三、QML自定义显示SpinBox的加减按键图片及显示值效果

QT应用篇 一、QT上位机串口编程 二、QML用Image组件实现Progress Bar 的效果 三、QML自定义显示SpinBox的加减按键图片及显示值效果 文章目录 QT应用篇前言一、qml需求二、使用组件1.SpinBox组件2.SpinBox中QML的使用 总结 前言 记录自己学习QML的一些小技巧方便日后查找 QT的…

rsync备份工具

有了同步源服务器之后&#xff0c;就可以使用rsync工具来执行远程同步了&#xff0c;本节介绍的备份操作均在客 户机&#xff08;发起端&#xff09;执行&#xff0c;实际上&#xff0c;同步源与发起端可以是同一台主机&#xff08;当然这种情况不常见&#xff09;&#xff0c;…

腾讯云轻量服务器和云服务器区别对比(超详细)

腾讯云轻量服务器和云服务器CVM该怎么选&#xff1f;不差钱选云服务器CVM&#xff0c;追求性价比选择轻量应用服务器&#xff0c;轻量真优惠呀&#xff0c;活动 https://curl.qcloud.com/oRMoSucP 轻量应用服务器2核2G3M价格62元一年、2核2G4M价格118元一年&#xff0c;540元三…

【12.28】转行小白历险记-刷算法04

01两两交换链表中的节点 整体思路 1.要修改后一个节点的指向一定要知道前一个节点的指向才可以改变后面一个节点的 2.分情况奇数和偶数节点&#xff0c;终止条件很重要 3.虚拟头节点&#xff0c;是对我们操作的指针是不是头节点进行判断 02删除链表的倒数第N个节点 思路 …

大数据与人工智能|万物皆算法(第三节)

要点一&#xff1a;数据与智能的关系 1. 一切的核心都是数据&#xff0c;数据和智能之间是密切相关的。 数据是对客观现实的描述&#xff0c;而信息是数据转化而来的。 例如&#xff0c;24是数据&#xff0c;但说“今天的气温是24摄氏度”是信息&#xff0c;而说“班可以分成24…

oracle与mysql的分析函数(窗口函数)

分析函数定义 在SQL语句中&#xff0c;很多查询语句需要进行GROUP BY分组汇总&#xff0c;但是一旦经过分组&#xff0c;SELECT返回的记录数就会减少。为了保留所有原始行记录&#xff0c;并且仍可以进行分组数据分析&#xff0c;分析函数应运而生。 Oracle 8i 版本开始支持窗…

java在线票务系统(选座)Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java servlet 在线票务系统&#xff08;选座&#xff09;管理系统是一套完善的java web信息管理系统 系统采用serlvetdaobean&#xff08;mvc模式)&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要…

MongoDB主从复制,一文打尽!

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

Hadoop安装笔记2单机/伪分布式配置_Hadoop3.1.3——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

紧接着上一篇博客&#xff1a;Hadoop安装笔记1&#xff1a; Hadoop安装笔记1单机/伪分布式配置_Hadoop3.1.3——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2&#xff1a;离线数据处理-CSDN博客https://blog.csdn.net/Zhiyilang/article/details/135…

K8s实战-基于LivenessProbe健康检查

LivenessProbe探针用于判断容器是否存活&#xff0c;如果探测到容器不健康&#xff0c;则kubelet将杀掉该容器&#xff0c;然后根据重启策略处理。 LivenessProbe的实现方式&#xff1a; ExecAction&#xff1a;在容器内部执行一个命令&#xff0c;如果该命令的返回码为0&…

右键菜单“以notepad++打开”,在windows文件管理器中

notepad 添加到文件管理器的右键菜单中 找到安装包&#xff0c;重新安装一般即可。 这里有最新版&#xff1a;地址 密码:f0f1 方法 在安装的时候勾选 “Context Menu Entry” 即可 Notepad的右击打开文件功能 默认已勾选 其作用是添加右键快捷键。即&#xff0c;对于任何…

定期修改公司数据协议的重要性

目录 ​编辑 为公司和客户数据提供更好的安全性 利用现代数据分析工具 标准化您的数据收集流程 改善数据的使用 增强您的营销和销售活动 定义数据分类指南 创建更具凝聚力和协作性的团队 遵守法律法规 结论 企业主可以使用许多对其成功至关重要的工具&#…

【UE5.1】程序化生成Nanite植被

目录 效果 步骤 一、下载Gaea软件和树林资产 二、使用Gaea生成贴图 三、 生成地形 四、生成草地 五、生成树林 六、生成湖泊 七、其它功能介绍 7.1 调整树林生成的面积 7.2 让植物随风飘动 7.3 玩家和植物互动 7.4 雪中树林 7.5 环境音效 效果 步骤 一、下载Ga…

图的操作实验

图的操作 一、 实验目的 &#xff08;1&#xff09;掌握图的邻接矩阵和邻接表存储结构。 &#xff08;2&#xff09;熟练图的邻接表的基本运算。 &#xff08;3&#xff09;加深图的深度优先遍历算法和广度优先遍历算法的理解。 &#xff08;4&#xff09;领会最小生成树和…

Spring高手之路-Spring事务的传播机制(行为、特性)

目录 含义 七种事务传播机制 1.REQUIRED&#xff08;默认&#xff09; 2.REQUIRES_NEW 3.SUPPORTS 4.NOT_SUPPORTED 5.MANDATORY 6.NEVER 7.NESTED 含义 事务的传播特性指的是当一个事务方法被另一个事务方法调用时&#xff0c;这个事务方法应该如何进行&#xff1f; 七…

Clion 项目使用dbg-macro控制台输出ANSI转义,输出颜色文本。

#Clion如何输出ANSI转义 首先源于&#xff0c;引入dbg-macro后&#xff0c;运行发现控制台全部是 C:\Users\WuXiangGuJun\CodeSpace\ClionCodeProjects\Tina\cmake-build-debug\tests\tests.exe ?[02m[..a\tests\src\main.cpp:16 (main)] ?[0m?[36mmessage?[0m ?[01m&q…

【计算机网络实验】educoder实验八 IPV6网络及其路由 头歌

第一关 IPV6网络基础 //千万不要破坏文档原有结构与内容&#xff01;&#xff01;&#xff01; //以下均为判断题&#xff0c;F&#xff1a;表示错误&#xff0c;T&#xff1a;表示正确 //答案必须写在相应行末尾括号内&#xff0c;F与T二选一&#xff0c;大写 // 1、ipv6协议…