【C#】Winform NanUI 0.77版本 读取本地资源(扩展功能)
一、前言
在NanUI官方的文档中,原本是有一个NanUI.FileResourceHandler的扩展包的,但现在官方已经无法下载了,现在只有0.88版本中有一个NanUI.LocalFileResource程序包,而0.77版本只剩下了一个读取嵌入式资源的程序包。
关于NanUI:NanUI | .Net/.Net Core界面组件NanUI 0.7版正式发布 - 林选臣 - 博客园
在扩展功能之前,请参考[资源处理器]-04 自定义资源处理器 - 知乎 ,我参考这个帖子进行扩展的,也不知道改的对不对,总之功能是实现了。
二、搭建环境
将NanUI0.77源码拷贝到你的项目中,将源码中的Resources.Designer.cs代码复制到你项目中的Resources.Designer.cs 中,
Resources.Designer.cs 中要加入的代码:
/// <summary> /// 查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。 /// </summary> internal static System.Drawing.Icon DevToolsIcon { get { object obj = ResourceManager.GetObject("DevToolsIcon", resourceCulture); return ((System.Drawing.Icon)(obj)); } } /// <summary> /// 查找类似 var NanUI = NanUI || {}; /// ///(function(target) { /// const CMD_ATTR_PREFIX = "nanui-command"; /// /// const RAISE_FUNC_NAME = "__nanui_raiseHostWindowEvent"; /// /// const GLOBAL_CLICK_HANDLER_REGISTERED = /// "__nanui_global_click_handler_registered"; /// /// if (!window.hasOwnProperty(RAISE_FUNC_NAME)) { /// window[RAISE_FUNC_NAME] = function(eventName, data) { /// window.dispatchEvent(new CustomEvent(eventName, { detail: data })); /// }; /// } /// /// if (!(GLOBAL_CLICK_HANDLER_REGISTERED in window)) { /// windo [字符串的其余部分被截断]"; 的本地化字符串。 /// </summary> internal static string FrameGlobalRegistrationScript { get { return ResourceManager.GetString("FrameGlobalRegistrationScript", resourceCulture); } } /// <summary> /// 查找类似 var NanUI = NanUI || {}; /// ///(function (target) { /// var hostWindow = { /// minimize: function () { /// native function Minimize(); /// return Minimize(); /// }, /// maximize: function () { /// native function Maximize(); /// return Maximize(); /// }, /// restore: function () { /// native function Restore(); /// return Restore(); /// }, /// close: function () { /// native function Close(); /// return [字符串的其余部分被截断]"; 的本地化字符串。 /// </summary> internal static string HostWindowExtension { get { return ResourceManager.GetString("HostWindowExtension", resourceCulture); } } /// <summary> /// 查找类似 /// P.O.W.E.R.E.D BY /// ███╗ ██╗ █████╗ ███╗ ██╗██╗ ██╗██╗ /// ████╗ ██║██╔══██╗████╗ ██║██║ ██║██║ /// ██╔██╗ ██║███████║██╔██╗ ██║██║ ██║██║ /// ██║╚██╗██║██╔══██║██║╚██╗██║██║ ██║██║ /// ██║ ╚████║██║ ██║██║ ╚████║╚██████╔╝██║ /// ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ /// S.I.N.C.E 2016 /// 的本地化字符串。 /// </summary> internal static string nanui { get { return ResourceManager.GetString("nanui", resourceCulture); } } /// <summary> /// 查找类似 var NanUI = NanUI || {}; /// ///(function (target) { /// /// target.__defineGetter__("version", function () { /// native function Version(); /// return Version(); /// }); /// ///})(NanUI); 的本地化字符串。 /// </summary> internal static string NanUIExtension { get { return ResourceManager.GetString("NanUIExtension", resourceCulture); } } /// <summary> /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// </summary> internal static System.Drawing.Bitmap ShadowTemplate { get { object obj = ResourceManager.GetObject("ShadowTemplate", resourceCulture); return ((System.Drawing.Bitmap)(obj)); } }
读取资源的代码也会有几个地方报错,比如,Bootstrap.cs中的Announce方法,由于源码使用的命名空间不一样,无法读取到方法,这里改为你项目的命名空间就好了
下面的NanUI077_SourceCode为我的命名空间
Log(NanUI077_SourceCode.Properties.Resources.nanui.White().OnDarkRed());
接下来将源码中的Resources文件夹拖拽到你的项目中,这些资源都用来显示浏览器的控制台。
打开Resources.resx,点击添加资源,将Resources文件夹所有文件选中添加,就如下图所示。
另外,将允许不安全代码勾选上,否则源码中的部分代码会报错。
如果你的源码正常运行,成功显示页面和控制台,js调用c# ,和c#调用js都正常,说明各方面搭建成功,可以开始下面的步骤。
我项目结构如下图,部分文件夹是我自己加的
打开ResourceHandlerRegister.cs ,这个脚本没有可以自己新建,这里我是导入了官方的嵌入式资源源码,所以已经有这个脚本了,这些源码可以搜索作者的github可以自行下载。
using System; namespace NetDimension.NanUI { public static class ResourceHandlerRegister { //读取嵌入式资源 //参考:https://zhuanlan.zhihu.com/p/109022286 public static Bootstrap UseAssembledResource(this Bootstrap _, ResourceHandlerScheme scheme, string domain, string basePath = null) { //GC.Collect(); Bootstrap.RegisterCustomResourceHandler(() => new AssembledResource(scheme, domain, basePath)); return _; } //REST资源处理器 //参考:https://zhuanlan.zhihu.com/p/109023845 public static Bootstrap UseRestfulService(this Bootstrap _, ResourceHandlerScheme scheme, string domain, Action<RestfulService.RestfulServiceProvider> provider = null) { //GC.Collect(); Bootstrap.RegisterCustomResourceHandler(() => { var resourceHandler = new RestfulServiceResource(scheme, domain); provider?.Invoke(RestfulService.RestfulServiceProvider.Create(resourceHandler)); return resourceHandler; }); return _; } //读取本地资源目录 //参考:https://zhuanlan.zhihu.com/p/109023019 public static Bootstrap FileResource(this Bootstrap _, ResourceHandlerScheme scheme, string domain, string filePath)// 如果您的资源处理器有其他参数,参数表因添加在末尾处) { //GC.Collect(); Bootstrap.RegisterCustomResourceHandler(() => new CustomResourceFactory(scheme, domain, filePath)); return _; } } }
新建脚本 CustomResourceFactory.cs
using Chromium; using NetDimension.NanUI.ResourceHandler; namespace NetDimension.NanUI { public class CustomResourceFactory : CustomResource { private string LocalDomain = string.Empty; public CustomResourceFactory(ResourceHandlerScheme scheme, string domain, string viewFolder) : base(scheme, domain) { string top = scheme == ResourceHandlerScheme.Http ? "http://" : "https://"; LocalDomain = string.Format("{0}{1}", top, domain); } protected override ResourceHandlerBase GetResourceHandler(string schemeName, CfxBrowser browser, CfxFrame frame, CfxRequest request) { return new CustomResourceHandler(LocalDomain); } } }
新建脚本 CustomResourceHandler.cs
using Chromium; using NetDimension.NanUI.ResourceHandler; using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; namespace NetDimension.NanUI { public class CustomResourceHandler : ResourceHandlerBase { private string LocalDomain = string.Empty; protected override FormiumResponse GetResponse(FormiumRequest request) { FormiumResponse response = new FormiumResponse(); if (request.Method != Method.GET) { Console.WriteLine("============[CustomResourceHandler]非Git请求"); response.Status = (int)System.Net.HttpStatusCode.NotFound; return response; } string physicalFilePath = string.Empty; if (ReadFile.Instance.FilePathList.Count > 0) { int leng = request.RequestUrl.Length; int start = LocalDomain.Length + 1; string indexPath = request.RequestUrl.Substring(start, leng - start); for (int i = 0; i < ReadFile.Instance.FilePathList.Count; i++) { if (ReadFile.Instance.FileNameList[i].Equals(indexPath)) { physicalFilePath = ReadFile.Instance.FilePathList[i]; break; } } } else { MessageBox.Show("[CustomResourceHandler] ReadFile 中资源列表 FilePathList 为空"); response.Status = (int)System.Net.HttpStatusCode.NotFound; return response; } if (string.IsNullOrEmpty(physicalFilePath)) { MessageBox.Show("[CustomResourceHandler] physicalFilePath 路径为空"); response.Status = (int)System.Net.HttpStatusCode.NotFound; return response; } response.ContentStream = File.OpenRead(physicalFilePath); response.MimeType = CfxRuntime.GetMimeType(Path.GetExtension(physicalFilePath).Trim('.')) ?? "text/plain"; return response; } public CustomResourceHandler(string localDomain) { LocalDomain = localDomain; } } public class ReadFile { private static ReadFile _instance = null; public static ReadFile Instance { get { if (_instance == null) { _instance = new ReadFile(); } return _instance; } } private List<string> _FilePathList = new List<string>(); public List<string> FilePathList { get => _FilePathList; } //web前端代码在不同的文件夹可能出现同名文件,所以这里并没有使用字典这样的数据结构 private List<string> _FileNameList = new List<string>(); public List<string> FileNameList { get => _FileNameList; } private string ViewFullPath = string.Empty; public void Init(string dir) { if (_FilePathList.Count <= 0) { ViewFullPath = System.IO.Path.Combine(Application.StartupPath, dir); GetDirectoryFileList(ViewFullPath); } } private void GetDirectoryFileList(string path) { DirectoryInfo directory = new DirectoryInfo(path); FileSystemInfo[] filesArray = directory.GetFileSystemInfos(); foreach (var item in filesArray) { if (item.Attributes == FileAttributes.Directory) { GetDirectoryFileList(item.FullName); } else { _FilePathList.Add(item.FullName); int leng = item.FullName.Length; int start = ViewFullPath.Length + 1; string newPath = item.FullName.Substring(start, leng - start); if (newPath.Contains(@"\")) newPath = newPath.Replace(@"\", "/"); _FileNameList.Add(newPath); } } } private ReadFile() { } } }
调用,Program.cs
using NetDimension.NanUI; using System; using System.Windows.Forms; namespace NanUI077_SourceCode { static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); string View = "View"; //读取web前端文件夹所有的资源 ReadFile.Instance.Init(View); Bootstrap .Initialize() //读取本地资源 .FileResource(ResourceHandlerScheme.Http, "www.app.local", View) .WithChromiumCommandLineArguments((procesName, cmd) => { // 在此处处理CEF的命令行参数 }) .WithChromiumSettings(settings => { // 在此处处理CEF的设置 }) .WhenLibCefNotFound(args => { // 如果NanUI启动器没有检测到正确的CEF以及ChromiumFX运行环境,将执行此处理过程。 MessageBox.Show("没有检测到Chromium Embedded运行环境,请确认libcef环境配置正确。", "libcef.dll is not found", MessageBoxButtons.OK, MessageBoxIcon.Error); }) .Run(() => { return new MainIndex(); }); } } }
在这里还可以提升一下读取的速度,在ReadFile类中加入下面方法,每次打开网页的时候,就不用老是重复去调用IO去读取本地资源了,我测试过,整体流畅度确实提升一些,但整体读取速度不如NanUI0.88版本。
private Dictionary<string, FileStream> StreamDic = new Dictionary<string, FileStream>(); /// <summary> /// 读取文件的FileStream /// </summary> /// <param name="areaPath">区域路径</param> /// <param name="fullPath">完整路径</param> /// <returns></returns> public FileStream GetFileStream(string areaPath,string fullPath) { if (StreamDic.ContainsKey(areaPath)) { return StreamDic[areaPath]; } else { //清除资源内存在 ResourceHandlerBase.cs 中的 OnRead 方法中 //我将 formiumResponse.Dispose(); 这句注释了,否则读取会报错 FileStream fileStream = File.OpenRead(fullPath); StreamDic.Add(areaPath, fileStream); return fileStream; } }
如果光这么写会报错,看代码中的注释,请将ResourceHandlerBase.cs 中 formiumResponse.Dispose() 这句代码注释
MainIndex.cs 脚本看我其他帖子,已经写了很多遍了,这里不贴代码了。
fx文件夹是cef的资源文件夹,这个如果没有,去你其他的NanUI0.77项目中拷贝过来放到Debug文件夹,或者安装NetDimension.NanUI.Runtime插件,版本选择0.77版。
安装完成后,在运行的时候,会自动生成cef文件。
在你的项目.exe文件同级目录下,加入一个View文件夹,将web前端代码放进去。
view文件夹
运行:
结束
如果这个帖子对你有用,欢迎 关注 + 点赞 + 留言,谢谢
end
猜你喜欢
- 【C#】C# System.Windows.Forms.DataVisualization Demo案例
- 简介DataVisualization 其实就是Winform 中自带的 Chart 控件,整个图形控件主要由以下几个部份组成:1.Annotations --图形注解集合2.ChartAreas --图表区域集合3.Legends --图例集合4.Series --图表序列集合(即图表数据对象集合)5.Titles --图标的标题集合每个集合具体介绍,可以参考下面的帖子,看完了介绍,一定对你理解这个插件
- 【C#】Winform NanUI 0.77版本 清除Cookie等本地缓存
- 目录需求NanUI0.88版本的缓存路径NanUI0.77版本的缓存路径试着实现功能添加扩展出现的问题解决问题结束需求清除web前端保存的一些的数据,或者清除浏览器缓存会用到。NanUI0.88版本的缓存路径在NanUI0.88版本中,只要在Program.cs启动模块中调用app.ClearCacheFile();就可以清除浏览的缓存了。0.88版本的缓存路径:"C:\\Users\\Administrator\\AppData\\Roaming\\Net Dimension Stu
- 【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
- 【C#】C# Winform程序之间通讯
- 实现原理通过Windows系统中 User32.dll 中的 FindWindow 方法来寻找系统正在运行的程序句柄,通过 SendMessage 方法来发送消息,winform 中的 WndProc 方法来接收消息,下面是SendMessage,FindWindow 这两个参数的具体介绍:1.SendMessage该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。该函数是应用程序和应用程序之间进行消息传递的主要手段之一 函数原型:I
- 【C#】从零开始用C#写一个桌面应用程序(二)一个表白程序
- 恶搞表白小程序如何添加按钮,如何添加属性和事件请移步前文。基础操作第一步:新建窗口 在工具箱内找到label和button,拖到form上,设置它们的size属性,autosize属性,text属性。第二步:添加事件为了实现我们的效果,需要给三个按钮分别设计点击事件,鼠标移入事件,鼠标点下事件。分别为click,mouseenter,mousedown事件。第三步:实现移动逻辑this获取form对象,clientsize获取实时大小,使用随机数值,设置对应按钮位置。将对应
- 【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
- 【C#】Winform NanUI 0.88版本 用官方源码搭建原生态开发环境
- 目录一、需求二、搭建原生开发环境1.导入源码2.解决源码报错错误1错误23.导入其他项目4.官方Demo运行效果三、创建自己的NanUI项目1.新建项目2.导入NanUI.Runtime扩展包3.添加NanUI程序集的引用4.MainIndex主界面相关代码5.Program程序入口相关代码6.读取本地前端文件的处理四、测试项目效果五、结束一、需求NanUI 插件确实很方便,但想改其中的需求怎么办,下面就来自己搭建NanUI 原生开发环境,在此很感谢作者免费的开源。官方源码地址:GitHub -
- 【C#】Winform NanUI 相关功能整合
- 目录NanUI 0.88版本 去掉启动界面(遮罩)NanUI 0.88版本 读取本地资源和嵌入式资源NanUI 0.77版本 打开控制台NanUI 0.77版本 C#调用多个参数的JS方法NanUI 0.77版本 传递数组参数NanUI 0.77版本 设置窗体全屏显示(类似Kiosk模式)NanUI 0.77版本 Bootstrap类 APINanUI 0.88版本 去掉启动界面(遮罩)启动界面是作者给我们显示公司产品的Logo用的,如果用不着可以去掉,但必须要更改源码,如果不想改源码,直接将启