现在,尽管WPF、UWP大行其道,大有把Winform打残干废的趋势。可是仍是有那么一波顽固不化的老家伙们固守着Winform,其中就包括我。css
好吧,既然都说Winform作得软件不如WPF界面美观效果绚丽,那么咱们就找一个方法让Winform也拥有漂亮的界面。DevExpress和ComponentOne都是不错的选择,Telerik虽然说是作Asp.net组件出生的,可是他家的UI for Winform作得也很不错。稍等,那问题来了,这些组件收费昂贵不说,并且是年付,起价都得几百美刀。对于我这种卢瑟程序员来讲,是支付不起这样高昂的费用的。那有人要说了,你咋不用破解版的呢?是的,能够用,并且也在用,可是这样一来个人心里是无比纠结的,用破解的盗版的,我就得欠另外那群程序员一大我的情,我这人虽然卢瑟,不喜欢欠别人人情!开个玩笑而已:)那么,有没有什么开源的,免费的,好用的解决方案呢?html
研究了一段时间,本人发现用浏览器作壳用HTML和CSS呈现软件界面是一种新趋势,固然这里指的浏览器不是.net本身带的WebBroswer控件,缘由不用我多说,你们都明白。这里说的是大名鼎鼎的CEF——Chromium Embedded Framework,通俗点也就是谷歌浏览器的核心了。CEF做为一个开源的浏览器核心组件对HTML五、CSS3和JS标准的支持不用我过多介绍,都是极好的。目前不少大厂都在使用CEF做为软件界面呈现,好比鹅厂大名鼎鼎的微信桌面版,网易的云音乐等等。因此,若是将CEF引入Winform做为界面呈现也是可行的。git
CEF的.net实现众多,最后相中了CefSharp和ChromimunFX两个开源项目,对比之,CefSharp除了传统的浏览器功能外还实现了离屏渲染,可是做为Winform忠狗的我来讲,我并不须要离屏渲染这项高端技术。最终ChromiumFX使用PInvoke的方式调用CEF的API,更接近“原生”,也更利于定制。通过个把月的披星戴月,在ChromiumFX的基础上本人完成了本身的CEF界面封装,暂时命名为NanUI for Winform,目前处于预览阶段。程序员
那么,下面就来看看本人封装的NanUI完成了什么工做。上图先~~github
NanUI目前处于预览开发阶段,还有一些问题并未解决,所以暂时不传GitHub,等稳定一些会考虑开放源代码。web
目前实现的功能:chrome
那么,下面分项介绍上面列举的功能。api
你觉得这里的无标题窗口就是单纯的把FormBorderStyle设置为None吗?固然不是。实现基础是调用DWM的DwmExtendFrameIntoClientArea,而后重绘了下窗口的边框,处理了各类鼠标事件。那有人要问了,那做着些事情不是狗解手吗,直接FormBorderStyle设置个None不就解决了?是的,这是能够解决,可是窗口就丧失了各类投影效果,各类放大缩小的效果。其次,还有各类鼠标消息和HITTEST消息,须要从ChromiumFX中传递到窗体上,要否则ChromiumFX一旦Dock而后Fill到窗口上,窗口还会相应鼠标事件才怪。因此,做为UI的基础,拖拽、放大、缩小等基本的操做都实现了。浏览器
在网页元素的css里打上“-webkit-app-region:drag”标记,就能够实现拖动该元素来移动窗体。服务器
如图所示,须要拖动的地方,就是drag,在标记过drag的元素上某些不给拖动的位置(例如关闭,最大化,最小化按钮位置)打上no-drag就拖动不了了。
其余没标记的地方随意,拖动事件会直接交给JS。
NanUI支持将作好的网页html、css、js、图片等文件直接做为嵌入资源编译到当前项目或者独立的DLL中,框架会自动调用嵌入的网页资源。既然用HTML作界面,HTML暴露在外被别人想改就改,那这个软件跟咸鱼有什么区别?因此网页文件做为内嵌资源功能被做为NanUI的核心功能之一,资源内嵌后,再给程序集加个强命,那要改你的软件就没那么简单了吧。
这也是本人为何不选择CefSharp的的缘由之一,CefSharp只支持编译成单一目标,很是不方便。ChromiumFX可以自动识别客户机环境加载对于的x86或是x64库。在此基础上NanUI扩展了自动下载CEF相关文件的功能,换句话说,发布项目的时候只须要发布项目自己生成的程序和程序集就能够了,软件首次在客户机运行时,会根据客户机的环境自动从指定网络位置下载CEF的相关文件,这样的好处就是软件发布的时候不用在软件自己内置CEF相关文件,极大的减少了打包文件的大小,并且不用去考虑客户机是32位系统仍是64位系统,简化发布流程。例如微信Windows客户端,安装包30多兆,其中至少25M是CEF相关文件,并且,微信客户端只有一个x86的版本,NanUI很好的规避了这个问题,文章最后的示例程序能够很好的证实这点。
最开始我就说了NanUI基于ChromiumFX开发,ChromiumFX原本应该有什么样的功能,NanUI就支持什么样的功能。要实现网页JS调用C#的类、方法等,C#操做网页DOM元素等,均可以经过ChromiumFX来实现。更多的功能,将会在后面的文章来介绍。
NanUI的基本功能就是上面说的这些。有了NanUI对Winform程序的支持,想作什么样的界面均可以实现了,不管是模仿个微信Window客户端、网易云音乐,仍是模拟下Win10里UWP那种款式的应用都是不在话下的。
下面,我讲介绍下NanUI的基本使用方法。
NanUI文件结构
NetDimension.NanUI.dll NetDimension.ZipCompress.dll
NanUI结构很是简单,“NetDimension.NanUI.dll”封装了ChromiumFX的所有内容并作了一些必要的修改,除此以外的其余内容就是NanUI的核心部分了。“NetDimension.ZipCompress.dll”是一个操做Zip文件的库,内容剽窃自DotNetZip,并作了一些修改。在此特别说明下,不论CEF、ChromiumFX仍是DotNetZip都采用BSD开源协议,协议容许我对上述项目进行剽窃、修改和随便用于商业目的,哦呵呵,因此别骂我无耻。
回归正题,在新建项目中引用“NetDimension.NanUI.dll”库便可。“NetDimension.ZipCompress.dll”仅做为须要远程下载CEF库时作解压ZIP文件用,实际项目中并不须要引用,若是项目发布时已在本地内嵌CEF框架,那么这个解压缩的库不须要随软件分发。
在此特别说明下CEF框架的文件夹结构:
fx与程序集放置在同一层级,若是项目编译时特地选择了x86架构或x64架构时,另一种架构的文件夹是不须要存在的,仅当项目编译类型为any cpu时须要x86和x64文件同时存在,NanUI会根据客户机的运行环境来自动选择加载x86或是x64架构的CEF库。当fx存在的时候NanUI将不会启用CEF库下载的特性,仅当fx文件夹内的CEF框架不存在时,NanUI才会自动从远程服务器下载CEF框架文件。
接下来,在Main函数中作一些简单的初始化的工做。
[STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); UIStartupManager.UseSharedFramework = true; if(UIStartupManager.InitializeChromium(args=> { args.Settings.LogSeverity = Chromium.CfxLogSeverity.Default; //这里能够对CEF进行一些设定 },args=> { Console.WriteLine(args.CommandLine); //输出命令行开关,看看启用或是禁用了哪些功能 })) { //初始化成功,加载程序集内嵌的资源到运行时中,固然也能够加载其余程序集里面的资源。 UIStartupManager.RegisterEmbeddedScheme(System.Reflection.Assembly.GetExecutingAssembly()); //启动主窗体 Application.Run(new frmWelcome()); } }
主窗体
public partial class frmWelcome : HtmlUIForm //继承HtmlUIForm { frmAbout aboutForm = null; public frmWelcome() : base("embedded://www/index.html") //设定启示页面,scheme是embedded就是咱们在Main里注册的当前程序集资源 { InitializeComponent(); //在js中注册一个方法来打开About窗口 UI.GlobalObject.AddFunction("showAboutForm").Execute += (sender, args) => { ShowAboutWindow(); }; //网页加载完成时触发事件 UI.LoadHandler.OnLoadEnd += (sender, args) => { //判断下触发的事件是否是主框架的 if(args.Frame.IsMain) { //执行JS,将当前的CEF运行版本等信息经过JS加载到网页上 var js = $"$client.setRuntimeInfo({{ api: ['{CfxRuntime.ApiHash(0)}', '{CfxRuntime.ApiHash(1)}'], cef:'{CfxRuntime.GetCefVersion()}', chrome:'{CfxRuntime.GetChromeVersion()}',os:'{CfxRuntime.PlatformOS}', arch:'{CfxRuntime.PlatformArch}'}});"; UI.ExecuteJavascript(js); } }; } private void ShowAboutWindow() { //由于当前环境中的JS代码跑在另外的线程上,因此在Control上扩展个UpdateUI方法,简化InvokeRequired流程 this.UpdateUI(() => { //显示字窗体的过程,不解释 if (aboutForm == null || aboutForm.IsDisposed) { aboutForm = new frmAbout(); aboutForm.Show(this); } else { aboutForm.Activate(); } }); } }
就是这么简单几步,漂亮的HTML界面加载到了你的Winform上,固然,前提是你得先有个“漂亮”的HTML界面先:)
好了,就像上面的图片里展现的同样,经过NanUI,Winform一样可以作出像其余两款软件那样的界面了。NanUI的预览版就先介绍到这里。在后续的文章中,我将以项目的形式再来深度的介绍NanUI在Winform中的各类运用。
下面的会提供上述图片中展现的DEMO程序及源代码提供给有兴趣的朋友下载把玩。
DEMO是用VS2015在Win10下编写的,.net须要4.5版本(Win10免安装,其余系统自行Google下载安装)可以运行。
感谢观看,谢谢你们,欢迎拍砖。
-------------------------------------------------- 分隔线 ----------------------------------------------------
应园友的要求,把NanUI所用技术的开源链接放置在此:
ChromiumFX - https://bitbucket.org/chromiumfx/chromiumfx
DotNetZip - https://github.com/haf/DotNetZip.Semverd .net 4.5的System.IO.Compress下面有操做Zip的类,正考虑要不要换成.net自带的,换了之后整个项目就只支持4.5了。
另一个CEF的.net实现
CefSharp - https://github.com/cefsharp/CefSharp/ NanUI最初的版本使用CefSharp做为基础,可是有些问题始终解决不了,才又转到ChromiumFX的。
另外今天看了评论,感谢各位提供了其余UI框架,不少以前都没见过,因此真是学习长进了。
也有朋友提出不少界面效果用WPF就能够实现,那问题来了,我不会WPF呀,呵呵,由于作过几年网页狗,因此仍是对HTML五、CSS3和Javascript要更亲切点。对于WPF和XAML,确实很强大,但路有多条,本着钻研的精神,应怀开放的态度,任何事物都能拿来尝试和学习。
NanUI也是机缘巧合之下研究了CEF才有想法作这么一个项目的。当时在跟某银行用了EXTJS作系统,为了客户端浏览器能正确加载EXTJS,解决方案就是Winform+CEF加壳硬把一个BS改为了客户端,因此后来了解了CefSharp项目,由于能力和学识有限,用CefSharp做为UI基础的时候有几个问题始终解决不了,所以才又发掘了ChromiumFX。
还有朋友提出NanUI有卵用?我的以为,存在即合理。既然腾讯,网易能用CEF弄出微信Windows客户端,网易云音乐,既然Cef永远甩不掉体积大的问题,我相信出于种种考虑,这两家大公司最终在其面向终端用户的应用软件中赤裸裸的、不计软件体积的引用了Cef,那咱们这些.net狗winform狗为什么不能拿CEF来作成Winform的界面壳呢?
我的拙见,欢迎讨论回复讨论或进群讨论,群号:241088256
NanUI for .NET Winform系列目录
通过了这一个多星期的调整与修复,NanUI for .NET Winform的稳定版已经发布。应广大群友的要求,现已将NanUI的所有代码开源。
GitHub: https://github.com/NetDimension/NanUI
Release: https://github.com/NetDimension/NanUI/releases
若是你喜欢NanUI项目,你能够参与到NanUI的开发中来,固然你也能够更直接了当的支持个人工做,使用支付宝或微信扫描下面二维码请我喝一杯热腾腾的咖