基于.Net CEF 实现 Vue 等前端技术栈构建 Windows 窗体应用

news2025/2/27 4:48:59

零、参考资料

1、https://github.com/cefsharp/CefSharp/wiki/Quick-Start-For-MS-.Net-5.0-or-greater

2、https://github.com/cefsharp/CefSharp/wiki/Quick-Start

3、https://github.com/cefsharp/CefSharp/wiki/General-Usage#javascript-integration

一、安装 Nuget 包

https://www.nuget.org/packages/CefSharp.WinForms

安装 CefSharp.WinForms 包后会显示 Readme.txt,

二、配置项目

<!-- CefWindowsFormsApp.csproj -->
<PropertyGroup Condition="'$(PlatformTarget)' == 'x64'">
  <RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">win-x64</RuntimeIdentifier>
  <SelfContained Condition="'$(SelfContained)' == ''">false</SelfContained>
</PropertyGroup>

三、加载远程网页示例

使用 ChromiumWebBrowser 加载百度首页,

// Form1.cs
using CefSharp;
using CefSharp.WinForms;
using System.Windows.Forms;

namespace CefWindowsFormsApp
{
    public partial class Form1 : Form
    {
        private static ChromiumWebBrowser browser;

        public Form1()
        {
            InitializeComponent();
            AddChromiumWebBrowser();
        }

        /// <summary>
        /// Create a new instance in code or add via the designer
        /// </summary>
        private void AddChromiumWebBrowser()
        {
            browser = new ChromiumWebBrowser("www.baidu.com");
            this.Controls.Add(browser);
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            // Load a url
            browser.LoadUrl("https://www.baidu.com/");
        }
    }
}

这这个示例中,我们引入了 CefSharp 库,在 Form1 窗体中添加了浏览器控件 ChromiumWebBrowser ,并且在窗体启动时加载百度首页,

四、加载本地网页示例

首先创建一个 Vue 项目,

# 使用 Vite
cnpm create vite@latest

# cd vite-project
# cnpm i

接着完成前端的开发之后,打包静态资源,

npm run build

然后在 WinForm 项目下创建 Resources 文件夹,把前端打包的 dist 文件夹下的文件全部复制过来,并且文件属性设置为“嵌入的资源”,

最后通过 RegisterScheme 注册为本地资源访问,

// Form1.cs
using CefSharp;
using CefSharp.SchemeHandler;
using CefSharp.WinForms;
using System.Windows.Forms;

namespace CefWindowsFormsApp
{
    public partial class Form1 : Form
    {
        private static ChromiumWebBrowser browser;

        public Form1()
        {
            InitializeComponent();
            AddChromiumWebBrowser();
        }

        /// <summary>
        /// Create a new instance in code or add via the designer
        /// </summary>
        private void AddChromiumWebBrowser()
        {
            InitBrowser();

            browser = new ChromiumWebBrowser("http://cefsharp.test");
            this.Controls.Add(browser);

        }

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

            settings.RegisterScheme(new CefCustomScheme
            {
                SchemeName = "http",
                DomainName = "cefsharp.test",
                SchemeHandlerFactory = new FolderSchemeHandlerFactory(rootFolder: @"..\..\..\..\CefWindowsFormsApp\Resources",
                            hostName: "cefsharp.test", //Optional param no hostname/domain checking if null
                            defaultPage: "index.html") //Optional param will default to index.html
            });

            Cef.Initialize(settings);
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            // Load local url
            browser.LoadUrl("http://cefsharp.test");
        }       
    }
}

效果如下,

五、调用 JS 代码

1、JS 无返回值

窗体页面调整,新增一个 Button 、一个 Pane,

注意,JavaScript 只能在 V8Context 中执行,这里的示例通过实现 IRenderProcessMessageHandler 接口、绑定 LoadingStateChanged 、FrameLoadEnd 两个事件来实现 DOM 加载时弹窗、页面资源加载完毕弹窗、主页面加载完毕弹窗,通过 “DoAlert” 按钮绑定事件来实现手动弹窗,

// Form1.cs
using CefSharp;
using CefSharp.SchemeHandler;
using CefSharp.WinForms;
using System.Windows.Forms;

namespace CefWindowsFormsApp
{
    public partial class Form1 : Form
    {
        private static ChromiumWebBrowser browser;

        public Form1()
        {
            InitializeComponent();
            AddChromiumWebBrowser();
        }

        /// <summary>
        /// Create a new instance in code or add via the designer
        /// </summary>
        private void AddChromiumWebBrowser()
        {
            InitBrowser();

            browser = new ChromiumWebBrowser("http://cefsharp.test");
            browser.RenderProcessMessageHandler = new RenderProcessMessageHandler();
            // Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
            
            browser.LoadingStateChanged += (sender, args) =>
            {
                // Wait for the Page to finish loading
                if (args.IsLoading == false)
                {
                    browser.ExecuteScriptAsync("alert('All Resources Have Loaded');");
                }
            };

            // Wait for the MainFrame to finish loading
            browser.FrameLoadEnd += (sender, args) =>
            {
                // Wait for the MainFrame to finish loading
                if (args.Frame.IsMain)
                {
                    args.Frame.ExecuteJavaScriptAsync("alert('MainFrame finished loading');");
                }
            };
            BrowserPanel.Controls.Add(browser);

        }

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

            settings.RegisterScheme(new CefCustomScheme
            {
                SchemeName = "http",
                DomainName = "cefsharp.test",
                SchemeHandlerFactory = new FolderSchemeHandlerFactory(rootFolder: @"..\..\..\..\CefWindowsFormsApp\Resources",
                            hostName: "cefsharp.test", // Optional param no hostname/domain checking if null
                            defaultPage: "index.html") // Optional param will default to index.html
            });

            Cef.Initialize(settings);
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            // Load a url
            browser.LoadUrl("http://cefsharp.test");
        }


        public class RenderProcessMessageHandler : IRenderProcessMessageHandler
        {
            public void OnContextReleased(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame)
            {
                throw new System.NotImplementedException();
            }

            public void OnFocusedNodeChanged(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IDomNode node)
            {
                throw new System.NotImplementedException();
            }

            public void OnUncaughtException(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, JavascriptException exception)
            {
                throw new System.NotImplementedException();
            }

            // Wait for the underlying JavaScript Context to be created. This is only called for the main frame.
            // If the page has no JavaScript, no context will be created.
            void IRenderProcessMessageHandler.OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
            {
                const string script = "document.addEventListener('DOMContentLoaded', function(){ alert('DomLoaded'); });";

                frame.ExecuteJavaScriptAsync(script);
            }
        }

        private void DoAlertBtn_Click(object sender, System.EventArgs e)
        {
            browser.ExecuteScriptAsync("alert('Hello World!');");
        }

    }
}

效果如下,

2、JS 有返回值

        private async void DoAlertBtn_ClickAsync(object sender, System.EventArgs e)
        {
            var script = @"(function() { let val = 1 + 1; return val; })();";
            JavascriptResponse response = await browser.GetBrowser().MainFrame.EvaluateScriptAsync(script);
            browser.ExecuteScriptAsync(string.Format("alert(' 1 + 1 = {0}');", (int)response.Result));
        }

六、Browser 调试器

browser.ShowDevTools();

七、app.manifest 清单文件

该清单文件是为了兼容 Win7、8、10 等系统差异,

<!-- example.exe.manifest -->
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <assemblyIdentity
        type="win32"
        name="Contoso.ExampleApplication.ExampleBinary"
        version="1.2.3.4"
        processorArchitecture="x86"
    />
    <description>Contoso Example Application</description>
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <!-- Windows 10/11 -->
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> <!-- * ADD THIS LINE * -->
        </application>
    </compatibility>
</assembly>

八、发布

项目右键,选择 Release x64 模式“重新生成”,在 bin 目录下生成文件,

需要把该目录的所有文件复制到另一台相同 .Net 版本的电脑才能运行。

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

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

相关文章

计算机网络文章荟萃

脑残式网络编程入门(二)&#xff1a;我们在读写Socket时&#xff0c;究竟在读写什么&#xff1f;-网络编程/专项技术区 - 即时通讯开发者社区! 1.什么是 socket - 掘金2.socket 的实现原理 - 掘金本文讲述了 socket 在 linux 操作系统下的数据结构&#xff0c;以及阻塞 IO 利用…

RHCE---作业3

一.判断磁盘空间 1、判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查一次磁盘剩余空间。 # 为了方便测式使用每分钟发送一封邮件&#xff0c;若想要每天定时检查则需要将前两个*改为0 0 [roottimeserver ~]…

Unity protobuf中repeated转C#文件List只读问题

Unity protobuf中repeated转C#文件List只读问题 介绍问题解决方案总结 介绍 工具这里我就不多介绍了&#xff0c;如果有用到ProtoGen工具的可以继续看一下我后面的方法。 问题 如下图所示&#xff0c;我这里随便用了一个.proto文件&#xff0c;看下我这里面的repeated标记的…

el-form动态增减数据的问题,编辑时候input输入不了

新增的时候可以展示&#xff0c;但是编辑在点新增就没有效果 原因&#xff1a;改变了数组内的值&#xff0c;但是页面没有重新渲染 <el-form-item label"信息:" required><div style"display: flex; align-items: flex-end"><div><e…

Spring MVC常用十大注解

Spring MVC常用十大注解 一&#xff0c;什么要使用注解 使用注解可以简化配置&#xff0c;提高代码的可读性和可维护性。通过注解可以实现依赖注入&#xff0c;减少手动管理对象的代码量。注解还支持面向切面编程&#xff0c;实现切面、切入点和通知等。此外&#xff0c;注解提…

maven仓库改国内源

今天准备复现漏洞环境&#xff0c;发现太慢&#xff0c;需要配置国内源 file -> settings 搜索maven 修改settings.xml&#xff0c;这里的需要修改两个文件 1.上图的settings.xml文件 2.idea的maven模块 settings.xml文件将原来的注释掉&#xff0c;然后把阿里的添加上&…

【机器学习合集】激活函数合集 ->(个人学习记录笔记)

文章目录 1. S激活函数(sigmoid&Tanh)2. ReLU激活函数3. ReLU激活函数的改进4. 近似ReLU激活函数5. Maxout激活函数6. 自动搜索的激活函数Swish 1. S激活函数(sigmoid&Tanh) Sigmoid函数在机器学习中经常用作激活函数&#xff0c;但它在某些情况下容易出现梯度消失问题…

QWidget快速美化-蓝色边框圆角按钮

将代码复制进QPushButton的样式表 效果: 代码: QPushButton{ color:#52DCFE;border:2px solid #52DCFE;border-radius:5px; }QPushButton::hover{background-color:#52DCFE;color:#ffffff; }QPushButton::pressed,QPushButton::checked{background-color:#52DCFE;color:#ffff…

学习vue3

一、入门 1.引入外部库 ①直接将所有的js都通过script标签引入到html文件中&#xff0c;所有的js资源在web页面中都能通用。 ②使用js引用js&#xff08;ES6&#xff09;&#xff0c;模块导入与导出 2.模块是只读引用 这段话是在解释 Vue.js 中的概念和用法。在 Vue.js 中&a…

​​​​​​​Python---练习:使用while嵌套循环打印 9 x 9乘法表

案例 使用while嵌套循环打印 9 x 9乘法表 思考 之前做过打印出三角形&#xff0c;那个三角形是5行的&#xff0c;这次打印9行的三角形。可以先使用while嵌套循环打印9行的直角三角形 相关链接Python---练习&#xff1a;打印直角三角形&#xff08;利用wihle循环嵌套&#xf…

Ubuntu下载、安装QGIS软件的方法

本文介绍在Linux操作系统Ubuntu版本中&#xff0c;通过命令行的方式&#xff0c;配置QGIS软件的方法。 在Ubuntu等Linux系统中&#xff0c;可以对空间信息加以可视化的遥感、GIS软件很少&#xff0c;比如ArcGIS下属的ArcMap就没有对应的Linux版本&#xff08;虽然有ArcGIS Serv…

Kafka简单入门02——ISR机制

目录 ISR机制 ISR 关键概念 HW和LEO Java使用Kafka通信 Kafka 生产者示例 Kafka 消费者示例 ISR机制 Kafka 中的 ISR&#xff08;In-Sync Replicas&#xff09;机制是一种用于确保数据可靠性和一致性的重要机制。ISR 是一组副本&#xff0c;它包括分区的领导者&#xff…

CCF CSP认证历年题目自练Day38

题目 试题编号&#xff1a; 201409-3 试题名称&#xff1a; 字符串匹配 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   给出一个字符串和多行文字&#xff0c;在这些文字中找到字符串出现的那些行。你的程序还需支持大小写敏感…

进程之操作系统的概念

再小的努力&#xff0c;乘以365都很明显。文章目录 操作系统操作系统的概念设计操作系统的目的 管理 ps:如何理解管理如何进行管理 操作系统管理软硬件资源小总结系统调用和库函数的概念小总结 操作系统 在讲述进程的时候我们先讲述一下操作系统&#xff08;os&#xff09;,因…

基于Java的小说下载网站管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

支持多用户协作的API测试工具:Apipost

在当今快速发展的数字化时代&#xff0c;API已成为企业与开发者实现数据互通、应用集成的重要桥梁。然而&#xff0c;随着API数量的不断增加&#xff0c;API开发、调试、测试、文档等工作也变得越来越复杂。为了解决这一痛点&#xff0c;一款名为Apipost的API协同研发工具应运而…

Python基础入门例程6-NP6 牛牛的小数输出

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 示例1 解答&#xff1a; 说明&#xff1a; 描述 牛牛正在学习Python的输出&#xff0c;他想要使用print函数控制小数的位数&#xff0c;你能帮助它把所有读入的数据都保留两位小数输出吗&#xff1f; 输入描述&a…

006:vue使用lottie-web实现web动画

文章目录 1. 简介2. 优点3. 效果4. 安装使用5. lottie-web 常用方法6. Lottie-web 常用的事件 1. 简介 官方介绍&#xff1a;Lottie 是一个库&#xff0c;可以解析使用AE制作的动画&#xff08;需要用bodymovie导出为json格式&#xff09;,支持web、ios、android、flutter和re…

LeetCode 22. 括号生成【字符串,回溯;动态规划】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

基于Java的线上花店管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…