您的当前位置:首页>全部文章>文章详情

【C#】Winform NanUI 0.77版本 JS和C#相互调用

CrazyPanda发表于:2024-02-06 20:41:04浏览:393次TAG:

目录

一、导入插件

二、常用方法

三、C#和JS相互调用

1.C# 调用JS

2.JS调用C#方法

3.完整版C#代码

4.完整版JS代码

结束




一、导入插件

用的NanUI版本0.77

20210129140851680.png

参考官方地址:https://docs.formium.net/zh-hans/tutorial/first-app.html


二、常用方法

基础代码:

using NetDimension.NanUI;
using NetDimension.NanUI.Browser;
 
class MainWindow : Formium
{
    //网页的地址
    public override string StartUrl => "https://www.google.com";
    //边框模式
    public override HostWindowType WindowType => HostWindowType.Standard;
    //这里写null就好
    protected override Control LaunchScreen => null;
 
    public MainWindow()
    {
        Title = "第一个NanUI应用"
    }
 
    protected override void OnWindowReady(IWebBrowserHandler browserClient)
    {
 
    }
 
    protected override void OnRegisterGlobalObject(JSObject global)
    {
 
    }
 
    //网页的大小和布局
    protected override void OnStandardFormStyle(IStandardHostWindowStyle style)
    {
        base.OnStandardFormStyle(style);
 
        style.Width = 1280;
        style.Height = 720;
        style.Icon = System.Drawing.SystemIcons.WinLogo;
        style.StartPosition = FormStartPosition.CenterScreen;
    }
}

启动页面也需要修改一下:

using NetDimension.NanUI;
 
static class Program
{
    /// <summary>
    ///  The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        //Application.Run(new Form1());
 
          Bootstrap
          .Initialize()
          .Run(() => new MainWindow());  
    }
}


三、C#和JS相互调用

1.C# 调用JS

假设页面中有如下Javascript的函数sayHello,它的作用是在DOM中创建一个包含有“Hello NanUI!”字样的p元素。

function sayHello() {
    var p = document.createElement("p");
    p.innerText = "Hello NanUI!";
 
    var container = document.getElementById("hello-container");
    container.appendChild(p);
}

示例中,该函数并没有在Javascript环境里调用,而是在页面加载完成后使用NanUI的ExecuteJavascript方法来调用它。ExecuteJavascript方法执行的返回结果为一个bool类型,它指示了这次有没有成功执行。

在窗体的构造函数中,通过注册 Formium 的 LoadHandler 中的 OnLoadEnd 事件来监测页面加载完成的情况,并在页面加载成功后调用JS环境中的函数 sayHello。


C#:

protected override void OnWindowReady(IWebBrowserHandler browserClient)
{
    browserClient.LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
}
 
private void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
{
    if (e.Frame.IsMain)
    {
        //C#调用网页中的JS脚本中sayHollo方法,这里,并没有返回参数,仅仅是让浏览器打印一个log而已
        WebBrowser.ExecuteJavascript("sayHollo()");
 
        //C#调用网页中JS脚本 带有返回参数的方法
        WebBrowser.EvaluateJavascript("returnValue('C#')", (value, exception) =>
        {
            if (value.IsString)
            {
                var jsValue = value.StringValue;
                MessageBox.Show(jsValue);
            }
        });
    }
}

这里调用了JS中的两个方法:sayHollo,returnValue

JS:

function sayHollo() {
    alert("网页alert: Hollo!");
}
 
function returnValue() {
    return "JS 返回 嘻嘻嘻!";
}

效果:

20210129140851680.png

20210129140851680.png


===============================

在需要获取返回值的情况下

上面的例子中通过ExecuteJavascript方法来成功调用了JS环境中的函数。但不难发现,这种调用方式C#是没有接收到任何返回值的。但实际的项目里,我们是需要从JS环境获取到返回值的,这时候使用ExecuteJavascript将不能满足需求,使用另外一个方法EvaluateJavascript可以帮助我们从JS环境中获得JS函数的返回值。

假如有另外一个Javascript函数sayHelloToSomeone,它能接收一个字符传参数,在函数体中拼接并返回拼接后的字符串。

function sayHelloToSomeone(who) {
    return "Hello " + who + "!";
}

同样的,在上面例子LoadHandler的OnLoadEnd事件中我们来执行sayHelloToSomeone,并通过C#传递参数并获取拼接后的返回值。EvaluateJavascript方法通过一个回调Action来获取JS环境中的返回值。这个Action有两个参数,第一个是返回值的集合,第二个是JS环境的异常对象,如果函数正确执行,那么第二个参数为null

namespace CommunicateBetweenJsAndCSharp
{
    using NetDimension.NanUI;
    public partial class Form1 : Formium
    {
        public Form1()
            : base("http://res.app.local/www/index.html",false)
        {
            InitializeComponent();
 
            LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
        }
 
        private void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
        {
            // Check if it is the main frame when page has loaded.
            if(e.Frame.IsMain)
            {
                EvaluateJavascript("sayHelloToSomeone('C#')", (value, exception) =>
                {
                    if(value.IsString)
                    {
                        // Get value from Javascript.
                        var jsValue = value.StringValue;
 
                        MessageBox.Show(jsValue);
                    }
                });
            }
        }
    }
}

在上面的示例中,通过我们可以明确知道JS函数sayHelloToSomeone的返回值一定为String类型,因此在C#的回调中直接使用Value的StringValue属性来获取JS函数的字符传返回值。但在实际的应用中,有可能并不完全知道返回值的类型,因此需要使用Value中内置的各个判断属性来逐一筛选返回值。

需要注意的是,Value的类是是ChromiumFX中的CfrV8Value类型,它是一个非常重要的类型,基本上所有在C#与CEF间的通信都是由这个类型来完成的。



2.JS调用C#方法

上面演示了如何用 C# 来调用 Javascript 中的函数,那么下面的内容将介绍如何使用 Javascript 来调用C#中的对象、属性和各种方法。

在此之前,需要介绍NanUI窗体基类Formium中的重要属性GlobalObject,您可以把他理解成Javascript环境中的window对象。如果您需要在Javascript环境下使用C#中的各种对象、属性和方法,都需要将这些对象、属性、方法注册到GlobalObject里。


C#:

protected override void OnRegisterGlobalObject(JSObject global)
{
    var myObject = global.AddObject("my");
 
    #region 添加属性
    //添加一个属性:name
    var nameProp = myObject.AddDynamicProperty("name");
    //Get属性
    nameProp.PropertyGet += (prop, args) =>
    {
        //要返回的字符串
        args.Retval = "这是C#的一个Get属性:name";
        args.SetReturnValue(true);
    };
    //Set属性
    nameProp.PropertySet += (prop, args) =>
    {
        var value = args.Value;
        args.SetReturnValue(true);
    };
    #endregion
 
    #region 添加方法
    //添加一个方法 showCSharpMessageBox
    var showMessageBoxFunc = myObject.AddFunction("showCSharpMessageBox");
    showMessageBoxFunc.Execute += (func, args) =>
    {
        var stringArgument = args.Arguments.FirstOrDefault(p => p.IsString);
        if (stringArgument != null)
            MessageBox.Show(stringArgument.StringValue);
        else
            MessageBox.Show("Js传递的参数为空!");
    };
 
    //添加一个具有返回参数的方法
    var getArrayFromCSFunc = myObject.AddFunction("getArrayFromCSharp");
    getArrayFromCSFunc.Execute += (func, args) =>
    {
        var jsArray = args.Arguments.FirstOrDefault(p => p.IsArray);
        if (jsArray != null)
        {
            //获取数组的长度
            int len = jsArray.ArrayLength;
            //创建一个新的数组
            CfrV8Value arr = CfrV8Value.CreateArray(len);
            for (int i = 0; i < len; i++)
            {
                //获取JS传过来数组的值
                int v = jsArray.GetValue(i).IntValue;
                //+1后,放入新的数组
                arr.SetValue(i, CfrV8Value.CreateInt(v + 1));
            }
            //作为返回参数
            args.SetReturnValue(arr);
        }
    };
 
    //接收JS的回调,并将自己的参数传递过去
    var callbackTestFunc = myObject.AddFunction("callbackTest");
    callbackTestFunc.Execute += (func, args) =>
    {
        var callback = args.Arguments.FirstOrDefault(p => p.IsFunction);
        if (callback != null)
        {
            //创建一个Object类型的变量
            var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
            //添加一个Bool类型的值:success
            callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
            //添加一个string类型的值:text
            callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);
            //用ExecuteFunction执行JS传递过来的回调,并将自己设置的变量callbackArgs传递给JS
            callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });
        }
    };
 
    #endregion
}

JS添加一个按钮,用来调用C#注入的方法:

function on_Click() {
    // alert("点击了按钮");
    //调用C#中注入的属性
    alert(my.name);
    //调用C#中注入的方法(无返回值)
    my.showCSharpMessageBox("我是参数!");
    //调用C#中注入的方法(返回一个数组)
    var arr = [1, 2, 3];
 
    var retArr = my.getArrayFromCSharp(arr);
    if (retArr) {
        alert("网页alert:" + retArr);
    }
    
    //调用C#并传入一个JS的回调
    my.callbackTest(sayByeBye);
};
 
function sayByeBye(obj) {
    var str = "参数success:" + obj.success + "   参数text:" + obj.text
    alert("网页alert: " + str);
}


3.完整版C#代码

using Chromium;
using Chromium.Remote;
using NetDimension.NanUI;
using NetDimension.NanUI.Browser;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace CSharpCallJS
{
    //参考:https://docs.formium.net/zh-hans/tutorial/js-context.html
    public class myform1 : Formium
    {
        //指定启动时访问的 Url 地址,这里用的是本地地址
        public override string StartUrl => @"E:\CSharp Project\NanUI_Test\CSharpCallJS\Viwe\index.html";
        //指定 WindowType 属性,选择窗体以原生样式显示还是使用无边框样式
        public override HostWindowType WindowType => HostWindowType.Standard;
 
        protected override Control LaunchScreen => null;
 
        public myform1()
        {
            Title = "第一个NanUI应用";
        }
 
        protected override void OnWindowReady(IWebBrowserHandler browserClient)
        {
            browserClient.LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd;
        }
 
        protected override void OnRegisterGlobalObject(JSObject global)
        {
            var myObject = global.AddObject("my");
 
            #region 添加属性
            //添加一个属性:name
            var nameProp = myObject.AddDynamicProperty("name");
            //Get属性
            nameProp.PropertyGet += (prop, args) =>
            {
                //要返回的字符串
                args.Retval = "这是C#的一个Get属性:name";
                args.SetReturnValue(true);
            };
            //Set属性
            nameProp.PropertySet += (prop, args) =>
            {
                var value = args.Value;
                args.SetReturnValue(true);
            };
            #endregion
 
            #region 添加方法
            //添加一个方法 showCSharpMessageBox
            var showMessageBoxFunc = myObject.AddFunction("showCSharpMessageBox");
            showMessageBoxFunc.Execute += (func, args) =>
            {
                var stringArgument = args.Arguments.FirstOrDefault(p => p.IsString);
                if (stringArgument != null)
                    MessageBox.Show(stringArgument.StringValue);
                else
                    MessageBox.Show("Js传递的参数为空!");
            };
 
            //添加一个具有返回参数的方法
            var getArrayFromCSFunc = myObject.AddFunction("getArrayFromCSharp");
            getArrayFromCSFunc.Execute += (func, args) =>
            {
                var jsArray = args.Arguments.FirstOrDefault(p => p.IsArray);
                if (jsArray != null)
                {
                    //获取数组的长度
                    int len = jsArray.ArrayLength;
                    //创建一个新的数组
                    CfrV8Value arr = CfrV8Value.CreateArray(len);
                    for (int i = 0; i < len; i++)
                    {
                        //获取JS传过来数组的值
                        int v = jsArray.GetValue(i).IntValue;
                        //+1后,放入新的数组
                        arr.SetValue(i, CfrV8Value.CreateInt(v + 1));
                    }
                    //作为返回参数
                    args.SetReturnValue(arr);
                }
            };
 
            //接收JS的回调,并将自己的参数传递过去
            var callbackTestFunc = myObject.AddFunction("callbackTest");
            callbackTestFunc.Execute += (func, args) =>
            {
                var callback = args.Arguments.FirstOrDefault(p => p.IsFunction);
                if (callback != null)
                {
                    //创建一个Object类型的变量
                    var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor());
                    //添加一个Bool类型的值:success
                    callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly);
                    //添加一个string类型的值:text
                    callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly);
                    //用ExecuteFunction执行JS传递过来的回调,并将自己设置的变量callbackArgs传递给JS
                    callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs });
                }
            };
 
            #endregion
        }
 
        protected override void OnStandardFormStyle(IStandardHostWindowStyle style)
        {
            base.OnStandardFormStyle(style);
 
            style.Width = 800;
            style.Height = 600;
            style.Icon = System.Drawing.SystemIcons.WinLogo;
            style.StartPosition = FormStartPosition.CenterScreen;
        }
 
        private void LoadHandler_OnLoadEnd(object sender, Chromium.Event.CfxOnLoadEndEventArgs e)
        {
            if (e.Frame.IsMain)
            {
                //C#调用网页中的JS脚本中sayHollo方法,这里,并没有返回参数,仅仅是让浏览器打印一个log而已
                WebBrowser.ExecuteJavascript("sayHollo()");
 
                //C#调用网页中JS脚本 带有返回参数的方法
                WebBrowser.EvaluateJavascript("returnValue('C#')", (value, exception) =>
                {
                    if (value.IsString)
                    {
                        var jsValue = value.StringValue;
                        MessageBox.Show(jsValue);
                    }
                });
            }
        }
    }
}

4.完整版JS代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        function on_Click() {
            // alert("点击了按钮");
            //调用C#中注入的属性
            alert(my.name);
            //调用C#中注入的方法(无返回值)
            my.showCSharpMessageBox("我是参数!");
            //调用C#中注入的方法(返回一个数组)
            var arr = [1, 2, 3];
 
            var retArr = my.getArrayFromCSharp(arr);
            if (retArr) {
                alert("网页alert:" + retArr);
            }
            
            //调用C#并传入一个JS的回调
            my.callbackTest(sayByeBye);  
        };
 
        function sayHollo() {
            alert("网页alert: Hollo!");
        }
 
        function sayByeBye(obj) {
            var str = "参数success:" + obj.success + "   参数text:" + obj.text
            alert("网页alert: " + str);
        }
 
        function returnValue() {
            return "JS 返回 嘻嘻嘻!";
        }
    </script>
</head>
 
<body>
    <div>我的网页</div>
    <div>
        <button onclick="on_Click()">按钮</button>
    </div>
</body>
 
</html>


结束

如果这个帖子对你有用,欢迎 关注 + 点赞 + 留言,谢谢

end

原文链接https://blog.csdn.net/qq_38693757/article/details/109804336

猜你喜欢

【C#】Winform NanUI 0.88版本 JS和C#相互调用
目录一、需求版本二、实例JS调用C#注册的只读属性JS调用C#注册的字段JS调用C#注册的同步方法JS调用C#注册的异步方法C#注册一个方法,JS调用并传递参数C#注册一个方法,JS调用并接收C#返回值C#注册一个方法,接收JS的数组参数C#注册一个方法,接收JS的一个函数,执行这个JS函数,并将C#的值传递过去三、结束一、需求在软件的界面和软件逻辑分离后,最重要的就是要处理参数的传递,和函数的调用,因此存在JS中和C#相互调用的需求。版本NanUI 版本:0.8.80.191二、实例using
发表于:2024-02-06 浏览:381 TAG:
【C#】c#Windows桌面程序退入托盘及右键菜单
一. 退出托盘功能窗体加组件notifyIcon修改属性,属性中加入要在托盘显示时呈现的图标。添加MouseClick事件编辑代码:private&nbsp;void&nbsp;Form_Main_FormClosing(object&nbsp;sender,&nbsp;FormClosingEventArgs&nbsp;e) { &nbsp;&nbsp;&nbsp;&nbsp;e.Cancel&nbsp;=&nbsp;true; &nbsp;&nbsp;&nbsp;&nbsp;this.Hid
发表于:2024-01-28 浏览:401 TAG:
【C#】C# Winform 三层架构
一、介绍三层架构是 C# 桌面开发中比较常用的框架,是由&nbsp;表示层(UI)、业务逻辑层(BLL)和数据访问层(DAL)三层架构组成,目的是为了 “高内聚,低耦合”。开发人员分工更明确,将精力更专注于应用系统核心业务逻辑的分析、设计和开发,加快项目的进度,提高了开发效率,有利于项目的更新和维护工作。从三层架构可以看到,很类似于&nbsp;Web 前端开发的 MVC 框架(视图View,模型Model,控制Contorller),但本质上也有不同的地方,比如都有视图(三层中叫 UI),Mod
发表于:2024-02-03 浏览:295 TAG:
【C#】CSDK/IDE-VSCode 搭建 C# 开发环境
&nbsp;&nbsp;&nbsp;&nbsp;最近准备写&nbsp;C#&nbsp;的笔记总结专栏&nbsp;bug&nbsp;笔记本硬盘空间实在是不够用了 &nbsp;&nbsp;&nbsp;&nbsp;根本没有办法再安装一个&nbsp;Visual&nbsp;Studio&nbsp;集成开发环境了!!! &nbsp;&nbsp;&nbsp;&nbsp;在学&nbsp;Java&nbsp;的过程中基本都是用记事本和命令提示符……再也不想经历了 &nbsp; &nbsp;&nbsp;&amp;nbs
发表于:2024-01-28 浏览:437 TAG:
【C#】Winform解决方案打包成.exe 安装版Windows桌面应用程序
踩了几天的坑,慢慢爬出来了。帮助一下新手友人吧,高手请绕路。IDE Version:Visual Studio 20191.安装Microsoft Visual Studio Installer Project(1)打开Visual Studio 2019,扩展-&gt;管理扩展(2)搜索install,下载图中的扩展即可(我已经安装了,所以没有下载按钮)按照操作安装即可2.打包(1)右键 解决方案-&gt;添加-&gt;新建项目(2)搜索setup-&gt;选择 Setup Project-&amp;
发表于:2024-01-28 浏览:481 TAG:
【C#】C# Winform DataGridView 控件和 DataTable
目录一、概述二、DataTable 的用法1.创建表和列2.添加行3.取值和赋值4.删除行5.遍历 DataTable6.判断 DataTable 列中是否存在某个值7.设置主键8.获取&nbsp;DataRow 所在的行号9.DataTable 转换为 List10.将 List 转&nbsp;DataTable三、DataGridView 的用法1.绑定数据2.获取绑定的数据源3.获取 / 设置&nbsp;选中单元格的数据4.设置单元格的宽高结束一、概述DataGridView 控件提供用于
发表于:2024-02-04 浏览:368 TAG:
【C#】C# Winfrom Chart 图表控件 柱状图、折线图
目录一、参考二、柱状图1.新建项目2.修改图表样式3.绑定数据4.删除Series1图例1)使用属性窗体删除2)使用代码删除5.自定义X轴的刻度值1)使用List绑定2)使用LabelStyle.Format绑定6.自定义Y轴的刻度值7.X轴刻度值显示不全的解决方法8.修改X Y刻度值的字体样式9.X轴刻度值旋转90°10.禁用Y轴刻度线11.去掉Y轴刻度值12.改变柱子的宽度13.设置网格线的颜色14.设置网格线的线型三、折线图1.图表设置2.绑定数据结束效果:一、参考c# Chart设置样式
发表于:2024-02-02 浏览:425 TAG:
【C#】C# Winform 相册功能,图片缩放,拖拽,预览图分页
一、前言在一些项目中也会用到预览图片的功能,至于为什么有一个添加图片的按钮,是因为有些项目,比如视觉相关的项目,摄像头拍摄图片,然后显示在界面上,拍一次显示一张。另一个,就是分页功能,当预览图位置不够用时就会用到。当前软件的功能1.添加图片如果8个预览图都满了,会自动分页,就可以点击上一页,或者下一页了。2.点击预览图显示大图点击预览图,之前的拖拽和放大会自动复位3.大图可以拖拽,放大,缩小如果图片比较小,有这个功能就看到图片的更多细节了。4.图片倒序排列最后拍摄的图片,始终显示在前面,方便用户
发表于:2024-02-02 浏览:324 TAG:
【C#】c#开发桌面应用程序用什么框架
style="text-wrap: wrap;">在C#开发桌面应用程序时,可以使用以下几种常见的框架:</p><ol class=" list-paddingleft-2" style="width: 1529.1px; text-wrap: wrap;"><li><p>Windows Forms:这是一种由.NET Framework提供的GUI框架,它提供了丰富的GUI控件和易于使用的编程模型。Windows Forms在C#开发领域中使用非常广泛,并且已经存在多年,获得了广泛的支持和优化。</p></li></ol
发表于:2024-01-27 浏览:452 TAG:
【C#】C# Winform ListView用法
目录添加标题显示网格添加数据到表格中自定义其他属性结束添加标题在 Winfrom 界面中添加一个 ListView 组件,然后点击右上角的箭头,点击编辑列添加下面标题,然后点击确定此时 ListView 中还是一片空白,不能显示这些标题,在视图这里选择 Details就会如下图所示,虽然标题出来了,内容确实一块白版,此时还是觉得 DataGridView 组件好用啊显示网格此时,表格只是一片空白,可以在属性面板中设置,显示网格,如下图&nbsp;&nbsp;这时,就如下图所示,效果就出来了,但是
发表于:2024-01-31 浏览:379 TAG: