ACPF UI 框架设计与基础实现

世态人情,比明月清风更饶有滋味;可作书读,可当戏看。书上的描摹,戏里的扮演,即使栩栩如生,究竟只是文艺作品;人情世态,都是天真自然的流露,往往超出情理之外,新奇得令人震惊,令人骇怪,给人以更深刻的效益,更奇妙的娱乐。惟有身处卑微的人,最有机缘看到世态人情的真相,而不是面对观众的艺术表演。

—— 杨绛

一、ACPF UI 简介

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

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

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

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

如果该框架并不能为您提供解决方案,请考虑使用其他成熟框架例如 Electron/Tauri/WinFormium 等。

二、ACPF 插件模块

安装 CefSharp.Wpf ,这里使用的版本是 119.1.20,

三、Attribute 特性

JavascriptObjectAttribute 用于导出 .net 方法为 js 对象,其他 ConfigurationAttribute 用于注入对应的配置项,

1、JavascriptObjectAttribute

using System;

namespace AwesomeChromePresentationFoundationUI.Attributes
{
    /// <summary>
    /// 该注解代表将类作为 JavascriptObject 导出
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class JavascriptObjectAttribute : Attribute
    {
        /// <summary>
        /// 名字,通常为驼峰命名
        /// </summary>
        public string Name { get; set; }
    }
}

2、BrowserConfigurationAttribute

using System;

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

3、CefConfigurationAttribute 

using System;

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

4、MainViewConfigurationAttribute 

using System;

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

    }
}

四、Reflections 反射

AttributeUtil 用于扫描自定义 Attribute 的类,

1、AttributeUtil

using System;
using System.Linq;
using System.Reflection;

namespace AwesomeChromePresentationFoundationUI.Reflections
{
    public class AttributeUtil
    {
        /// <summary>
        /// 找到第一个带注解的类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static Type FindFirstAnnotatedClass<T>() where T : Attribute
        {
            return AppDomain.CurrentDomain.GetAssemblies()
               .SelectMany(a => a.GetTypes())
               .Where(t => t.IsClass && t.GetCustomAttribute<T>() != null)
               .FirstOrDefault();
        }

        /// <summary>
        /// 找到第一个带注解的类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="S">继承自S类</typeparam>
        /// <returns></returns>
        public static Type FindFirstAnnotatedClass<T, S>() where T : Attribute
        {
            return AppDomain.CurrentDomain.GetAssemblies()
               .SelectMany(a => a.GetTypes())
               .Where(t => t.IsClass && t.GetCustomAttribute<T>() != null && typeof(S).IsAssignableFrom(t))
               .FirstOrDefault();
        }
    }
}

五、Interfaces 接口

提供接口,引导自定义接口实现,

1、IBrowserConfiger

using AwesomeChromePresentationFoundationUI.Configs;

namespace AwesomeChromePresentationFoundationUI.Interfaces
{
    public interface IBrowserConfiger
    {
        BrowserConfiguration CreateCustomBrowserConfiguration();
    }
}

2、ICefConfiger

using AwesomeChromePresentationFoundationUI.Configs;

namespace AwesomeChromePresentationFoundationUI.Interfaces
{
    public interface ICefConfiger
    {
        CefConfiguration CreateCustomCefConfiguration();
    }
}

3、IMainViewConfiger


using AwesomeChromePresentationFoundationUI.Configs;

namespace AwesomeChromePresentationFoundationUI.Interfaces
{
    public interface IMainViewConfiger
    {
        MainViewConfiguration CreateCustomBaseFormConfiguration();
    }
}

4、IConfigurationExecuter


namespace AwesomeChromePresentationFoundationUI.Interfaces
{
    public interface IConfigurationExecuter
    {
        void Execute();
    }
}

5、CefConfigurationExecuter

using AwesomeChromePresentationFoundationUI.Configs;
using CefSharp;

namespace AwesomeChromePresentationFoundationUI.Interfaces.Implements
{
    public class CefConfigurationExecuter : IConfigurationExecuter
    {
        public void Execute()
        {
            CefConfiguration configuration = DefaultICefConfiger.CreateCustomCefConfiguration();
            Cef.Initialize(
                configuration.CefSettings,
                performDependencyCheck: configuration.PerformDependencyCheck,
                browserProcessHandler: configuration.BrowserProcessHandler
                );
        }
    }
}

六、Configs 配置

提取一些必要配置项并设置默认值,

1、BrowserConfiguration

using AwesomeChromePresentationFoundationUI.Constants;

namespace AwesomeChromePresentationFoundationUI.Configs
{
    public class BrowserConfiguration
    {
        /// <summary>
        /// 默认编码
        /// </summary>
        public string DefaultEncoding { get; set; }
        /// <summary>
        /// 加载 URL
        /// </summary>
        public string HomeUrl { get; set; }


        public BrowserConfiguration()
        {
            this.DefaultEncoding = SystemConstant.BROWSER_DEFAULT_ENCODING;
            this.HomeUrl = SystemConstant.BROWSER_DEFAULT_LOAD_URL;
        }
    }
}

2、CefConfiguration

using CefSharp;
using CefSharp.SchemeHandler;
using CefSharp.Wpf;
using System;
using System.IO;

namespace AwesomeChromePresentationFoundationUI.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()
            {
                Locale = "zh-CN",
                // Increase the log severity so CEF outputs detailed information, useful for debugging
                LogSeverity = LogSeverity.Verbose,
                //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
                CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
            };

            //Example of setting a command line argument
            //Enables WebRTC
            // - CEF Doesn't currently support permissions on a per browser basis see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access
            // - CEF Doesn't currently support displaying a UI for media access permissions
            //
            //NOTE: WebRTC Device Id's aren't persisted as they are in Chrome see https://bitbucket.org/chromiumembedded/cef/issues/2064/persist-webrtc-deviceids-across-restart
            settings.CefCommandLineArgs.Add("enable-media-stream");
            //https://peter.sh/experiments/chromium-command-line-switches/#use-fake-ui-for-media-stream
            settings.CefCommandLineArgs.Add("use-fake-ui-for-media-stream");
            //For screen sharing add (see https://bitbucket.org/chromiumembedded/cef/issues/2582/allow-run-time-handling-of-media-access#comment-58677180)
            settings.CefCommandLineArgs.Add("enable-usermedia-screen-capturing");

            //Disable GPU Acceleration
            settings.CefCommandLineArgs.Add("disable-gpu");

            // Don't use a proxy server, always make direct connections. Overrides any other proxy server flags that are passed.
            // Slightly improves Cef initialize time as it won't attempt to resolve a proxy
            settings.CefCommandLineArgs.Add("no-proxy-server");

            settings.RegisterScheme(new CefCustomScheme
            {
                SchemeName = "http",
                DomainName = "yushanma.acpf",
                SchemeHandlerFactory = new FolderSchemeHandlerFactory(rootFolder: this._defaultFrontendFolderPath,
                            hostName: "yushanma.acpf", //Optional param no hostname/domain checking if null
                            defaultPage: "index.html") //Optional param will default to index.html
            });

            this.CefSettings = settings;
            this.PerformDependencyCheck = true;
            this.BrowserProcessHandler = null;
        }

        /// <summary>
        /// 创建默认前端文件夹
        /// </summary>
        private void CreateDefaultFrontendFolderPath()
        {
            string frontendFolderPath = Path.Combine(Directory.GetCurrentDirectory(), "Frontend");

            if (!Directory.Exists(frontendFolderPath))
            {
                Directory.CreateDirectory(frontendFolderPath);
        

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【HTML 基础】元数据 meta 标签

文章目录 1. 设置字符集2. 描述网页内容3. 设置关键词4. 网页重定向5. 移动端优化注意事项结语 在网页开发中&#xff0c;<meta> 标签是一种十分重要的 HTML 元数据标签。通过巧妙使用 <meta> 标签&#xff0c;我们能够设置各种元数据&#xff0c;从而影响网页在浏…

Java21 + SpringBoot3集成七牛云对象存储OSS,实现文件上传

文章目录 前言实现步骤引入maven依赖修改配置文件创建七牛云配置类创建文件操作服务类创建文件操作控制器前端实现运行效果 总结 前言 近日心血来潮想做一个开源项目&#xff0c;目标是做一款可以适配多端、功能完备的模板工程&#xff0c;包含后台管理系统和前台系统&#xf…

flutter开发实战-可扩展popup弹窗template模版样式

flutter开发实战-可扩展popup弹窗template模版样式 最近在看到一个flutter_beautiful_popup&#xff0c;可以美化弹窗窗口样式。该插件通过一个template模版的类BeautifulPopupTemplate作为抽象的base类。 一、基类BeautifulPopupTemplate 在BeautifulPopupTemplate中&…

python推荐算法在汽车用品商城营销系统 django+flask

本论文拟采用计算机技术设计并开发的汽车营销中的设计与实践 &#xff0c;主要是为用户提供服务。使得会员可以在系统上查看汽车商品、汽车快讯、还可以咨询客服&#xff0c;管理员对信息进行统一管理&#xff0c;与此同时可以筛选出符合的信息&#xff0c;给笔者提供更符合实际…

Linux conda环境安装

一、软件预准备 cpu操作系统飞腾S2500银河麒麟V10 SP1 1.1.软件下载 官方网站找自己系统需要的版本&#xff1a; https://repo.anaconda.com/miniconda/或者&#xff0c;我们可以复制下载的链接&#xff0c;直接在服务器上下载&#xff0c;如&#xff1a; wget -c https:/…

Java代码实现基数排序算法(附带源码)

基数排序是一种非比较型整数排序算法&#xff0c;其原理是将整数按位数切割成不同的数字&#xff0c;然后按每个位数分别比较。由于整数也可以表达字符串&#xff08;比如名字或日期&#xff09;和特定格式的浮点数&#xff0c;所以基数排序也不是只能使用于整数。 1. 基数排序…

从0开始搭建、上传npm包

从0开始搭建、上传npm包 1、上传一个简单获取水果价格的包创建 vite 项目在项目根目录 src 文件夹中创建 index.ts 文件&#xff0c;文件内容如下&#xff1a;在 main.ts 文件中导入、导出上面创建的方法创建 vite.config.ts 配置文件&#xff0c;文件内容如下配置 package.jso…

Windows下Nginx启动等命令

1. winr 输入cmd 打开控制台 进入nginx 所在目录 cd D:\tools\nginx-1.20.2\nginx-1.20.22.启动 //执行后屏幕闪烁一下 start nginx任务管理器可以看到 nginx.exe 进程 说明启动成功 3.停止 nginx.exe -s stop4.重新加载配置文件 nginx.exe -s reload5.查看版本 nginx -…

数据结构与算法:图论(邻接表板子+BFS宽搜、DFS深搜+拓扑排序板子+最小生成树MST的Prim算法、Kruskal算法、Dijkstra算法)

前言 图的难点主要在于图的表达形式非常多&#xff0c;即数据结构实现的形式很多。算法本身不是很难理解。所以建议精通一种数据结构后遇到相关题写个转换数据结构的接口&#xff0c;再套自己的板子。 邻接表板子&#xff08;图的定义和生成&#xff09; public class Graph…

微服务入门篇:Nacos注册中心(Nacos安装,快速入门,多级存储,负载均衡,环境隔离,配置管理,热更新,集群搭建,nginx反向代理)

目录 1.Nacos安装1.官网下载2.解压到本地3.启动nacos 2.Nacos快速入门1.在父工程中导入nacos依赖2.给子项目添加客户端依赖3.修改对应服务的配置文件4.启动服务&#xff0c;查看nacos发现情况 3.Nacos服务多级存储模型4.NacosRule负载均衡5. 服务实例的权重设置6.环境隔离&…

第二届 N1CTF Junior WEB方向 部分题解WP

zako 题目描述&#xff1a;很简单的rce哦 启动环境&#xff0c;源码直接给了。 execute.sh #!/bin/bashreject(){echo ${1}exit 1 }XXXCMD$1awk -v str"${XXXCMD}" \ BEGIN{deny";&$(){}[]!#$%^&*-";for(i 1; i < length(str); i){char su…

ffmpeg操作实战001:视频+音频文件融合

一、功能需求 把视频文件video.mp4 和音频文件audio.wav融合在一起&#xff0c;输出视频文件output.mp4 二、操作指令 ffmpeg -i video.mp4 -i audio.wav -c:v copy -map 0:v:0 -map 1:a:0 output.mp4 三、参数说明 ffmpeg: 这是用于执行FFmpeg命令行工具的命令。-i video…

分析 cusolverDnSgeqrf 的具体算法

1. 分析实例 源码&#xff1a; #include<time.h> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<cuda_runtime.h> #include<cublas_v2.h> #include<cusolverDn.h> #define BILLION 1000000000L;void print_v…

vue 下载二进制文件

文章目录 概要技术细节 概要 vue 下载后端返回的二进制文件流 技术细节 import axios from "axios"; const baseUrl process.env.VUE_APP_BASE_API; //downLoadPdf("/pdf/download?pdfName" res .pdf, res); export function downLoadPdf(str, fil…

git整合分支的两种方法——合并(Merge)、变基(Rebase)

问题描述&#xff1a; 初次向git上传本地代码或者更新代码时&#xff0c;总是会遇到以下两个选项。有时候&#xff0c;只是想更新一下代码&#xff0c;没想到&#xff0c;直接更新了最新的代码&#xff0c;但是自己本地的代码并没有和git上的代码融合&#xff0c;反而被覆盖了…

【Script】使用pyOpenAnnotate搭建半自动标注工具(附python源码)

文章目录 0. Background1. Method2. Code3. Example: 雄鹿红外图像标注3.1 选择色彩空间3.2 执行阈值3.3 执行形态学操作3.4 轮廓分析以找到边界框3.5 过滤不需要的轮廓3.6 绘制边界框3.7 以需要的格式保存Reference本文将手把手教你用Python和OpenCV搭建一个半自动标注工具(包…

spring boot打完jar包后使用命令行启动,提示.jar 中没有主清单属性

在对springBoot接口中间件开发完毕后&#xff0c;本地启动没有任何问题&#xff0c;在使用package命令打包也没异常&#xff0c;打完包后使用命令行&#xff1a;java -jar xxx.jar启动发现报异常&#xff1a;xxx.jar 中没有主清单属性&#xff0c;具体解决方法如下&#xff1a;…

离散数学——特殊关系(笔记及思维导图)

离散数学——特殊关系&#xff08;笔记及思维导图&#xff09; 笔记来自【电子科大】离散数学 王丽杰

ensp实验合集(二)

实验6 VLAN划分....................................................................... - 30 - 实验7 路由器调试及常用命令使用........................................ - 42 - 实验8 配置静态路由器............................................................…

Python中的HTTP代理与网络安全

在当今数字化的世界里&#xff0c;网络安全已经成为我们无法忽视的重要议题。无数的信息在网络上传递&#xff0c;而我们的隐私和敏感数据也在这个过程中可能面临被窃取或滥用的风险。在Python编程中&#xff0c;HTTP代理作为一种工具&#xff0c;能够在网络安全方面发挥重要的…