当前位置:首页 > 开发教程 > .net教程 >

Sciter / HTML / C#基于桌面的应用程序演练

时间:2016-02-23 10:20 来源:互联网 作者:源码搜藏 收藏

本文介绍了如何通过 C# 使用Sciter通过使用创建基 于HTML 的桌面应用程序 SciterSharp 库(.NET绑定过Sciter API)。 为了快速启动我们的应用程序,我们使用一个Sciter引导模板,这有助于使我们的跨Windows和Linux应用程序编译。 Sciter是使桌面应用程序的

本文介绍了如何通过C#使用Sciter通过使用创建基于HTML的桌面应用程序SciterSharp库(.NET绑定过Sciter API)。为了快速启动我们的应用程序,我们使用一个Sciter引导模板,这有助于使我们的跨Windows和Linux应用程序编译。

Sciter是使桌面应用程序的一个多平台的HTML渲染引擎。在这些很酷的功能,它具有以下支持:
  • < - >为UI的本地集成主机通讯,DOM操作,资源跟踪,所有通过C#
  • 量好CSS3与使用Flex单位一个漂亮的布点系统
  • 通过TIScript语言脚本(JavaScript的扩展)
  • 一个脚本API的前端级DOM /风格操作,AJAX调用,JSON,...

这也是免费用于商业用途,虽然它不是开源。它分布作为你的C / C ++ SDK内找到本机共享库(DLL)。该SDK包含用于构建Windows,Linux和OSX。

Sciter技术在现实世界中的一些大的软件使用,证明多远,你可以去用它:ICQ客户端,诺顿,停住下,BitDefender,ESET杀毒软件。

Sciter / HTML / C#基于桌面的应用程序演练

该示例桌面应用程序使用“ 谷歌API客户端库.NET ”查询谷歌的字体  用于显示用户可用的字体列表和一个按钮来下载它们。这将需要本地C#编码以及HTML和脚本,用于使用户界面,以及该2层之间进行通信的混合。这样,您将获得如何创建一个位本机C#编码的应用涉及熟悉,并与异步资源加载,并在如何通过UI /原生层之间的数据。完整的源代码也可在GitHub上

Sciter / HTML / C#基于桌面的应用程序演练

Sciter代替,比如说,CefSharp或Electron.io的注意事项

目前已经有大量的用于在.NET应用程序中嵌入HTML内容选项。CefSharp和Electron.io似乎是最流行的,并且都使用铬作为下划线引擎。由于Sciter不是一个流行的Web浏览器,那么为什么我选择了它,而不是一个众所周知的HTML引擎像壁虎或铬与尖端HTML5技术的支持使用标准的发动机?那么,你需要为自己决定什么是适合你的,什么是适合你的项目。我所能做的就是告诉你什么让我采取Sciter,如何使用技术,并且解决它的缺点。

Sciter特定功能集

Sciter不尝试实现HTML5标准,不过,这并不意味着你之前的HTML / CSS知识不能被使用。以下是你可能需要考虑对不同内容的摘要:

  • CSS支持帐户的所有基本属性(全CSS2.1)和CSS3的一些重要的东西(边界半径,箱阴影,线性渐变,见CSS属性的支持片 ;也CSS布点有点Sciter具体的,主要由弯曲通过单位和“流:”属性,这比对CSS3 Flexbox的顺便说一句容易得多。
  • 脚本是通过TIScript语言所作的; 它不与标准的浏览器的API一致,它具有一个有据可查的它自己的API集; 但因为它是一个Javascript扩展,网络程序员将下跌完全熟悉它。
  • HTML5的特性之一,有Sciter等同于以下几点:绘图画布,SVG,的WebSockets API,<视频>,CSS动画/过渡,自定义字体(你可以使用例如FontAwesome); 其他HTML5功能你也许可以实现与一个位附加本地编码。

使用Sciter的优势

我为什么选择Sciter比其他引擎的原因在于,首先,Sciter是制作的桌面应用程序,而不是网页浏览器量身定做。我觉得这样的承诺所带来的它是如何被开发了的时候(很多善良已经10岁的道路)。

我对Sciter使用建议是,当你想为你的HTML应用良好的本地支持:你把所有的选择你喜欢的编程语言(D,C#,C ++,Python和德尔福,围棋),它具有操纵一个成熟的本地API的灵活性您的应用程序的每一个方面。

标准的浏览器引擎被设计成访问从网络服务器远程提供的网页,以执行它们沙箱,其中系统资源被严格控制。Sciter被设计为从任何来源处理资源:资源装载是完全可定制的,并且它也具有从BLOB的紧缩数据加载资源的API。

在TIScript你可以处理的系统资源(文件,套接字IPC)和原生层容易说话。因为,你在做桌面应用程序,假定你正在处理可信资源执行它Sciter没有什么太大的安全约束及其相关的开销。

铬是中小型应用的真正臃肿。铬集成原生层有严重的问题。例如,在上述这篇文章,你不能让复杂的JavaScript对象到C#层,则需要将其转换为JSON第一和发送的对象向后字符串。

  • Sciter不仅仅是跨平台,支持Windows和Linux / GTK和OSX,但它也有许多编程语言:C#,C ++,D,Python和Delphi和围棋(我是C#和D的作者和维护者的)
  • 轻量级:引擎是你需要沿着你的产品附带一个本机DLL
  • 高性能:有发动机启动无延时,如果其他人相比臃肿的HTML引擎具有更低的内存消耗,并绘制后端是GPU加速(Direct2D的在Windows,开罗Linux和CoreGraphics中的OSX)
  • 优秀的本地窗口集成:创建多个Sciter窗口实例,他们都共享同一个TIScript VM,因此您可以共享之间的数据; 航空DWM-启用了Windows,WS_EX_LAYERED窗口(桌面透明度); 允许创建本地Windows / HWND作为子DOM元素
    • 看样,您可以创建窗口的例子:http://misoftware.rs/Bootstrap/Templates
  • 可定制的本土资源加载; 定制调试输出消息
  • < - >本地集成DOM操作,DOM事件回调和TIScript原生API
    • CefSharp不公开一个DOM API; 与SciterSharp您可以查看/从C#操作DOM!这对于调试最有用的,因为DOM操作你通常可以通过脚本做
  • 随着版本3.3.1.4,你可以用它来 渲染UI在DirectX窗口,在这里看到和图像如下:
Sciter / HTML / C#基于桌面的应用程序演练

使用Sciter的缺点

  • 这不是一个所见即所得的环境类似的WebForms或WPF,你需要写HTML代码和预览造成视觉的sciter.exe工具(当然,如果你认为HTML是一个很好的方法,在所见即所得那么它真的不是一个劣势)
  • 缺乏HTML5的功能和W3C标准:不能简单地抓取像jQuery或引导图书馆和Sciter使用
  • Linux的/ GTK支持有许多HTML / CSS缺失的功能,如果相比于Windows的版本,这是比较成熟的; 我没有测试OSX支持,因为我不拥有一台苹果机=(但据说是因为在Windows中一样好

1.入门

要开始,你心里一定有什么,我们将在本文中实现和所涉及的目标:

-我们将步行通过创建一个桌面应用程序,显示可用谷歌字体列表与按钮又让用户下载一个.zip与整个字体系列
- 这整篇文章将在Visual Studio 2015年完成,但最后我将展示如何编译它使用的Linux的MonoDevelop
-The前端/ UI完全是用HTML / CSS和脚本与TIScript制成
-The后端在C#中,涉及:
     -Google .NET API:用于查询谷歌字体
     异步-Handling谷歌响应和返回的数据传递给UI层
     -我们使用SciterSharp库及其对很多事情API超过Sciter引擎,从UI通信资源加载
-我们从预制的IDE项目开始,我们从Sciter引导页面下载上线
     - 我们选择多平台的模板,所以我们可以很容易地编写Windows和Linux

所以上手,我们需要获得一些资源,因此遵循以下3个步骤。

下载Sciter引导包

由于我们要创建一个多平台的桌面应用程序,你必须明白,支持不同的操作系统意味着要处理不同的API集。通常你想在多个平台上工作的统一的API工作。但有时是不可能的,你必须诉诸使用OS特定API。在C#中做到这一点周围的平台特定的代码#如果/#ENDIF条件编译块。的Win32 API和GTK + 3 API:这种情况可能会在我们的例子,因为我们正在处理两个不同的操作系统和它们各自的窗口系统是必需的。

幸运的是,你不必太担心,因为我们将用做最小的样板代码模板开始。它不仅仅是代码,它也包含了适当的SciterSharp依赖配置,你可以在VS和MonoDevelop中编译您的应用程序打开的.sln,它包含两个项目(每个平台/ IDE)。

所以,去Sciter引导下载页面,并按照下列步骤操作:

- 步骤1:选择“视窗32-64bits和MONO / GTK 64位/ Visual Studio或MonoDevelop的> = 5.10 / C#”

- 步骤2:选择“多平台模板”

-步骤3:编写项目的标题-此文章中,我们使用  FontLister(标题名称必须遵循C#标识符规则)

- 步骤4:点击“下载”按钮

解压.zip内容,并在Visual Studio 2015年按Build按钮打开的.sln,等待它下载SciterSharp的NuGet包,然后运行该应用程序。Cooool,你已经有一个Sciter多平台应用程序的运行。这是不容易?

如果你得到编译错误,那是因为SciterSharp的NuGet没有正确下载。进入包管理器控制台,并尝试发出“更新的程序包-Reinstall”命令来修复它。

注意,这个解决方案包含两个项目。由于我们并不需要建立MONO / GTK项目于Windows系统(它甚至不会运行),可随时右键单击该项目项并选择“卸载项目”。

手动安装

SciterSharp可以下载并安装由你自己,如果你正在开始一个项目,并且不希望使用Sciter引导。

-安装它作为一个的NuGet包:为的WindowsMONO / GTK + 3

-Or下载从整个项目https://github.com/midiway/SciterSharp ; 我强烈建议这样做,因为这样的话,你可以调试和步骤在SciterSharp代码,看看它在做什么,这是一个非常小的项目呢

然而,这些方法不支持这篇文章,因为我们要开始Sciter引导模板代码,因为它是多平台的准备,我们希望我们的应用程序在Windows和Linux上运行。

安装的NuGet包,并获得谷歌API密钥

我们需要通过的NuGet包的其他.NET库。你必须将包安装到这两个项目(FontListerGTK和FontListerWindows)。你可以这样做右键单击“FontLister”解决方案项目和“管理的NuGet的解决方案包”(注意FontListerGTK项目必须加载)。
 
安装这些包的NuGet:
-Google.Apis.Webfonts.v1
-Newtonsoft.Json
 
你需要让自己的查询谷歌字体的谷歌API密钥。
-进入  谷歌开发者控制台
- 创建一个新项目
- 在总览页面,有一个输入其内容为“搜索所有100+的API'; 搜索“字体”
- 选择“Web字体开发者API”,然后点击蓝色的“启用API”按钮
- 现在去凭证/新凭证/服务器密钥
- 由于我们会从本地桌面应用程序仅查询谷歌的字体,简单的服务器密钥就足够了
- 按创建并弹出显示的API密钥,只需保存到某个地方

下载Sciter SDK

抓住Sciter SDK 从这里该SDK主要是使用C / C ++ API开发,但它也有所有Sciter二进制文件和工具。我们从SDK需要的是sciter.exe位于/ bin目录中找到工具。我建议你运行它,销任务栏中的图标。我们将使用这个工具,两件事情:

-你用它查看您编写HTML代码的结果; 你通常编辑HTML代码,并切换回sciter.exe和按F5刷新页面; 也就是说,sciter.exe就像一个浏览器为Sciter HTML内容; 它也有F12工具相当于DOM检查和脚本调试。

-它也可以访问到文件自带的SDK里面捆绑; 点击?标记按钮左侧的工具栏,并且将打开一个包含您使用的脚本所有TIScript API的描述,也教你关于语言; 您将在咨询了很多,相信我。

2.代码手 - >后端

在我们开始之前,我想向您推荐挫折的常见原因做这类桌面应用程序的时候,我们面对的问题。
它是Web开发单独的工作惯例两个人之间:一个人负责的UI / UX思(前端),以及其他负责业务逻辑,基于UI事件(后端)驱动程序。
随着Sciter,如Web开发,可以实现工作流的形式相同。但你会独自将不可避免地在同一时间做两件事,它可以是非常令人沮丧。
在做UI编码和思考,通常情况下,带着几分CSS和HTML的,你取得成果非常快,你能直观地看到结果。后端通常需要更多的精神坚韧的工作和思维方式的程序。问题是,这两种思维模式不兼容,好痛我的大脑时,我做的混合两件事。由于这样,我真的鼓励你努力习惯单独做这些事情,因为我会告诉你。
我们将与后端在哪里,在做实际的UI之前,我们将使用两种不同的UI成语定义的连接点开始。在Sciter有3个成语后端< - > UI沟通你可以在阅读的细节在这里
这是一个步行通过,我们将主要从默认的代码从引导模板添加或调整代码。

窗口创建

我们的应用程序的初始化文件Program.cs中,在那里你找到窗口创建代码,这是不言自明的。该SciterWindow类是用于创建和处理一个不可知论者的方法OS本地窗口为托管Sciter HTML页面。对于我们的FontLister,我改变了窗口的标题和大小,所以我结束了:
// 创建窗口
var wnd = new SciterWindow();
wnd.CreateMainWindow(800, 600);
wnd.CenterTopLevelWindow();
wnd.Title = "Font Lister";
在Windows只,您可以从SciterWindow类衍生物覆盖ProcessWindowMessage()虚方法,所以你可以处理的Win32消息。
 
从理论上讲,只需SciterWindow实例,你已经可以加载并调用LoadHtml(),例如显示一个HTML页面:

	
wnd.LoadHtml("<html><body>Hello World!</body></html>");
wnd.Show();
但是,我们希望得到更深入和控制有关HTML页面的加载一切,这就是为什么我们需要一个SciterHost实例来包装HTML加载过程。

网页托管解释

SciterHost类是控制沿托管HTML页面的生活诸多方面的核心部件。本质上,它让你跟踪以下通知了Sciter引擎产生:
-SC_LOAD_DATASC_DATA_LOADED使您能够控制资源加载,并在下一节解释。
SC_POSTED_NOTIFICATION你打电话SciterHost.PostNotification后()方法被接受; 因为在UI线程总是收到此消息是在多线程的情况下非常有用; SciterHost提供,你可以从一个工作线程用来执行在UI线程特定委托的InvokePost()方法。
SC_ATTACH_BEHAVIOR:一个请求到本机的行为(SciterEventHandler instace)附加到DOM元素。
SC_ENGINE_DESTROYED:产生之前发动机被破坏,关闭主窗口后。
SciterHost类有相应的overridables方法为你处理这些通知。
 
此外,SciterHost可以让你通过附加AttachEvh()方法的一个窗口级别的事件处理程序。此处理程序从网页接收的每个事件之前被分派到目标DOM元素。
 
引导程序代码来已经与需要设置一个SciterHost一切:
// 准备SciterHost然后加载页面
var host = new Host();
host.SetupWindow(wnd);
host.AttachEvh(new HostEvh());
host.SetupPage("index.html");
其实引导扩展SciterHost与主机类,所以托管相关的代码位于一个单独的类/文件(Host.cs)。
需要注意的是之前加载HTML页面,我们必须先调用SetupWindow()将SciterWindow到SciterHost相关联,还可选附加SciterEventHandler来接收即将被装载SetupPage页面的事件()。
 
从分组数据资源加载
随着SC_LOAD_DATASC_DATA_LOADED通知您可以跟踪和定制由你的HTML页面(HTML页面本身,图片,脚本,CSS)要求每个资源的加载或者你可以忽略它并保留默认加载机制。
你可以注意到,在从Host.cs文件BaseHost类,引导代码通过覆盖OnLoadData()方法使用一个自定义加载策略。

protected override SciterXDef.LoadResult OnLoadData(SciterXDef.SCN_LOAD_DATA sld)
{
    if(sld.uri.StartsWith("archive://app/"))
    {
        // load resource from SciterArchive
        string path = sld.uri.Substring(14);
        byte[] data = _archive.Get(path);
        if(data!=null)
            _api.SciterDataReady(_wnd._hwnd, sld.uri, data, (uint) data.Length);
    }
    return SciterXDef.LoadResult.LOAD_OK;
}
Sciter资源通过标准URL机制跟踪。我们在做什么,如果资源的URL开头存档://应用程序/(即:协议),我们从我们的SciterArchive实例加载资源持有我们所有的资源在一个BLOB压缩格式。这BLOB包含在文件ArchiveResource.cs并重新创建每次我们通过在项目中已经配置的预生成命令生成项目的时间。
注意从SciterArchive BLOB装车仅在释放模式完成。在调试模式的资源从文件系统直接加载。
BaseHost类SetupPage()方法是负责加载初始HTML页面并指定其URL和基础协议相关:文件:///或存档://应用程序/,这使得调试和发布模式加载策略之间的这种差异。
为什么这一切?因为我们的发布版本将包含包装中的.exe决策部署更加容易内的所有资源。我们的DEBUG版本将更快从文件系统加载资源。
 
GOOGLE 1 -装载,并通过GOOGLE字体列表到UI层。在“应用程序事件”的成语(主机- > UI
对于与谷歌的字体处理相关的事情,我们创建一个专用的类。整个类的代码是在文件中的数据/ GAPI.cs,你可以从成品样品.ZIP复制。
这个类需要解决的第一个任务是通过谷歌的API请求可用谷歌的字体列表,并通过此列表UI层。由于这个操作需要一定的时间,因为它从互联网上获取数据,你不希望在主UI线程出现这种处理,而是在后台线程。所以,在这里,实现它的代码:

public static void Setup()
{
    new Thread(() =>
    {
        var service = new WebfontsService(new Google.Apis.Services.BaseClientService.Initializer()
        {
            ApiKey = API_KEY
        });

        var request = service.Webfonts.List();
        request.Sort = WebfontsResource.ListRequest.SortEnum.Popularity;

        _fontlist = request.Execute().Items;// if you get an Exception here, plz disable your Firewall!
        Debug.Assert(_fontlist.Count > 0);
        ...
请确保你有设置API_KEY变量您的谷歌API密钥。谷歌的字体返回列表存储在一个静态变量“_fontlist,因为我们以后需要的列表中。
 
现在,我们需要把这个列表传递到UI层,它显示给用户的字体列表:
     ...
        // converts the Webfont list to JSON string
        string json = JsonConvert.SerializeObject(_fontlist);

        // converts the JSON string to SciterValue
        SciterValue sv = SciterValue.FromJSONString(json);

        // calls UI layer TIScript function with the font data
        Program.HostInstance.InvokePost(() =>
        {
            Program.HostInstance.CallFunction("View_OnFontList", sv);
        });
    }).Start();
}
在这里你找到“应用程序事件”互动的原则/成语的用法你可以阅读更多有关在这里但它是非常简单的:原生应用层简单地调用脚本函数将数据传递给UI层(主机- > UI通讯)
 
这是通过一个全球脚本函数的名称与Program.HostInstance.CallFunction()方法完成的(或命名空间一个)和任何数量的SciterValue参数。但是,请注意,此代码将在后台线程来执行。这是危险的,可能会导致数据损坏,因为我不知道TIScript 100%线程安全的。
最安全的是要切换回UI线程,并从那里做调用脚本。这就是为什么Program.HostInstance.InvokePost的使用(()=> {...})方法,将执行在UI线程上下文拉姆达参数。
 
SciterValue类是用来代表/在C#创建TIScript数据之一。对于从IList中让我们的SciterValue <WebFont>我们做一个小小的trickie转换。我们首先转换的IList <WebFont>以JSON字符串,然后用SciterValue.FromJSONString(JSON)的JSON解析到一个新的SciterValue。和它的作品非常好!
 
GOOGLE 2 -下载和GOOGLE字体保存为zip格式在“POST请求”的成语(UI - >主机- > UI
第二个任务我们GAPI C#类确实是下载一个给定的字体家族(可包含多个.TTF文件),在一个.zip收拾他们,并将其保存在指定文件夹。
处理它的方法非常简单,不言自明的,只是读到的资料。它的签名是:

public static void DownloadFont(string family, string savefolder) { ... }
我们通过字体的名称和路径在哪里保存的.zip。我们下载使用WebClient.DownloadFile()调用,这确实需要时间远程的字体文件,因此DownloadFont()方法不应该从UI线程调用的,而是从工作线程。
随着文件下载到临时文件夹,.NET已经从一个文件夹中的.zip文件,该文件通过调用发生打包文件,一个很好的API:

ZipFile.CreateFromDirectory(tmppath, savefolder + "/" + family + ".zip");
(您必须添加一个引用到System.IO.Compression.FileSystem装配使用这个API)
 
字体下载发生在用户点击我们的HTML页面的下载按钮,所以我们需要一种方法来检测这个UI事件触发的字体下载。我们不会阻止用户界面,同时下载正在发生,我们需要一种方法来告诉用户界面完成时。为此,我们使用“POST请求”的成语(UI - >主机 - > UI)。基本上这个成语UI要求有回调脚本函数一起为资源原生层,当资源是可用的,所以通过将结果返回给用户界面层主体应该调用。
 
执行此代码是在文件Host.cs:

protected override bool OnScriptCall(SciterElement se, string name, SciterValue[] args, out SciterValue result)
{
    result = null;
    switch(name)
    {
        case "Host_DownloadFont":
            string savefolder = args[0].Get("");
            string family = args[1].Get("");
            SciterValue async_cbk = args[2];

            Task.Run(() =>
            {
                bool res;
                try
                {
                    GAPI.DownloadFont(family, savefolder);
                    res = true;
                }
                catch(Exception)
                {
                    res = false;
                }

                if(async_cbk.IsUndefined())
                    return;// no callback provided

                Program.HostInstance.InvokePost(() =>
                {
                    async_cbk.Call(new SciterValue(res));
                });
            });

            return true;
    }
    return false;
}
在UI / HTML脚本代码,我们将调用view.Host_DownloadFont(文件夹,家庭功能(){...})时,下载按钮被按下,这在我们的主机类的我们OnScriptCall()C#处理结束。
引用:

在TIScript,只要您拨打“视图”变量的方法,而这个功能的方法是不确定的,Sciter引擎调用连接到您的SciterHost OnScriptCall()事件处理程序,给它一个机会来处理不存在的函数名。如果从返回'真'OnScriptCall处理程序,这意味着你处理呼叫和脚本虚拟机将不会触发“视图(View([对象视图]))没有方法- Host_DownloadFont”异常并停止执行脚本。

当脚本调用  view.Host_DownloadFont(文件夹,家庭功能(RES){...}),我们收到的给定的参数在C#作为SciterValue数组。从这个数组,我们手动前两个itens使用转换为字符串ARGS [0]获得(“”) 所以我们有savefolder和家人字符串变量(可以为所有基本的C#类做这样的转换,则Get()方法对INT获取(0),布尔获取(真),等过载..)。我们节省第三SciterValue阿根廷,脚本回调,作为原料SciterValue变量“async_cbk”。
 
我们的处理程序,然后开始运行在后台线程的GAPI.DownloadFont()过程的任务。需要注意的是,因为这取决于网络的可用性,所以其在try / catch块包围它可能会失败。当DownloadFont()完成后,我们有一个布尔结果是如果发生成功下载,我们将传回UI层作为标志。
 
正如在“应用程序事件”的成语,我们需要切换回UI线程通过使用调用脚本函数Program.HostInstance.InvokePost()。然后,我们只需使用SciterValue的call()方法传递布尔调用脚本回调结果作为SciterValue了。现在你知道,SciterValue是处理任何类型的数据TIScript多purpouse类。
 
后端测试
我们的后端的一切都在原地。从我们的Main()方法,我们的主机类调用SetupPage()后加载HTML页面,我们必须调用:
..
FontLister.Data.GAPI.Setup();
..
此方法GAPI类创建一个查询谷歌API的字体列表,然后通过调用脚本全局函数“View_OnFontList”通过列表UI层的线程(见GOOGLE 1节)。
 
因此,对于测试是否所有工作正常,只是把一个断点文件GAPI.cs其内容的46行:
..
Program.HostInstance.CallFunction( View_OnFontList”,SV); // - >断点这里
 ..
并开始调试我们的应用程序。它应该命中断点,否则检查是否有早期异常。因此,谷歌API的测试只是真的按F5调试我们的应用程序。
 
现在我们需要测试它会从我们的UI层被调用的方式调试我们的代码。正如所以我们会从C#直接模拟用户界面的要求,让你学会如何测试的东西没有前端。
 
这一行46后,把下面的一行47:

Program.HostInstance.CallFunction("View_OnFontList", sv);// line 46
Program.HostInstance.EvalScript("view.Host_DownloadFont(\"D:/\", \"Open Sans\", function(res) {})");// line 47
应该是这样的:
Sciter / HTML / C#基于桌面的应用程序演练
 
到底是什么它做什么?view.Host_DownloadFont是我们HostEvh事件处理类原生处理(见GOOGLE 2部分)的函数,因此当您从TIScript调用此函数,它结束beeing由C#代码处理。
我们现在做的就是通过模拟EvalScript从C#这个脚本调用()。我们通过作为参数TIScript代码在我们SciterWindow的全局命名空间执行。
 
什么会发生的是,它会调用我们在谷歌2节中定义的Host_DownloadFont处理程序。需要注意的是我们传递3个参数来Host_DownloadFont:
- “D:/”
- “打开三世”
- 功能(RES){}
分别是:目录中保存的.zip,字体家庭,和一个空的回调函数。
 
好了,现在你可以调试,看看是否一切工作正常。将断点在我们刚刚添加的47行,并在文件Host.cs断点,一行33按F5键,它应该首先再次命中47行,按F5,然后就应该打线33.现在你可以步骤中的代码,直到它到达GAPI.DownloadFont()。这个电话后,稍等一下,并检查文件“打开Sans.zip”在您的D创建:驱动程序。我们刚刚仿真和测试,当用户下载一个.zip一个给定的字体家庭会发生什么。删除47行。

3.代码手 - >前端

现在我们正在进入发展的一个全新的领域其中涉及纯HTML / CSS和脚本与TIScript语言。我可能会说这是比后端更容易,只要你有一点HTML和CSS的经验。即使你是在网络技术方面的专家,这是值得阅读本节,因为在Sciter HTML / CSS的支持有一些细微之处并非由标准的浏览器支持。TIScript拥有标准的JS很多差异,但它仍然一个Javascript语言一样。
 
当我们与后端做了,我们就可以编写和测试从后端完全不沾边的前端,所以不要求工作后端。
 
HTML
这是我们需要更换为index.html的内容中的所有HTML:

<html>
<head>
</head>

<body>
	<div .warning>Loading Google fonts..</div>
	<div #list />
</body>
</html>
这是标准的HTML,直到你注意到一些细微之处。注意,我们宣布<div>元素:
<DIV #list />
有两个Sciter具体的事情,在这里你必须知道。首先,请注意我们没有一个结束</ div>标签。如果元素包含没有孩子,可以完全省略结束标记,不管它是什么HTML标签。在浏览器中,<DIV>的总是需要关闭标签。
二,而不是用一个id =“XYZ”属性声明元素的ID,如<DIV ID =“名单”/> 我们可以简单地说#THE_ID,你会写在CSS中的ID选择。您可以为类属性做同样的,所以<DIV CLASS =“名单列表色”/>可以写成<DIV .list.list色/> 通过使用相同的语法从CSS中写一个元素的ID或类非常聪明的方法。Sciter支持更多的属性快捷方式,在这里看到
此外,在Sciter,你可以使用任何标记名称,例如<列表的的的细节> </列表的的的细节>但你也需要设置显示CSS属性,所以下面有必要进行列表的的的细节可见:

list-of-details
{
     display: block;// or inline, inline-block, ..
}
 
CSS
对于造型我们的页面,我们需要下列CSS <style>标签,你应该把在<head>标签中:

<style>
	body
	{
		margin: 0;
		padding: 10px;
		flow: vertical;
		background: #eee;
		font-family: system;
	}

	li
	{
		padding: 10px;
		margin-bottom: 10px;
		border: solid 1px #BBB;
		box-shadow: 0px 1px 1px #EEE;
		background: white;
	}

	h1 { margin: 0; margin-bottom: 10px; }

	b { font-size: 18px; }
	b.success { color: green; }
	b.error { color: red; }
</style>
没有什么好说的,这仅仅是标准的CSS。这里唯一的Sciter具体的事情是“流”属性,你可以阅读更多有关在这里本质上,它是对CSS3 Flexbox的布点的等效的,但其具有不同的命名和行为。
在'柔性'属性决定如何元素的儿童将被定位在里面。我们使用的“垂直”值说垂直布局元素,一是波纹管其他的,行,如果不管它的内嵌或块元素。
 
TIScript
脚本语言被认为是本地函数/组件和UI事件/元素间的胶水。此外,脚本的主要目的之一是更新DOM的状态,让您的动态添加到您的网页。

TIScript分隔不同的线程模型。HTML,CSS和脚本(后面UI代码)是基于assynchronous资源负载,而应用程序核心包括用于供给上的用户界面的同步程序,但是舒服,因为它不与用户界面和它的事件和线程模型并列。

对于我们的应用程序,这里是你需要添加到<head>标签中的所有脚本代码:


	
<script type="text/tiscript">
	function View_OnFontList(data)
	{
		$(.warning).remove();

		for(var item in data)
		{
			var el_item = self#list.$append(<li><h1>{item.family}</h1><button>Download Font Family</button></li>);
			el_item.family = item.family;
		}
	}

	self.on("click", "button", function() {
		var el_btn = this;
		var folder = view.selectFolder();
		if(folder)
		{
			el_btn.state.disabled = true;
			el_btn.text = "Downloading..";

			var family = el_btn.$p(li).family;
			view.Host_DownloadFont(folder, family, function(res) {
				if(res)
					el_btn.$after(<b .success>Download completed with success!</b>);
				else
					el_btn.$after(<b .error>Error downloading!</b>);
				el_btn.remove();
			});
		}
	});
</script>

需要注意的是TIScript代码必须 <脚本类型=“文/ tiscript”>标签,而不是简单地<script>标记之间犹豫。

我无法解释这个代码,因为它超出了本文的范围。您可以了解更多有关TIScript 这里但是它可以很容易地被JS开发商只通过读取它的理解。但是,请注意,从普通的JavaScript以下区别:

-strings文字只被允许使用双引号:“我的字符串”是有效的TIScript串,“我的字符串'是无效的语法; 
其中名称以$开头-函数/方法stringizer功能
     -the参数字面理解为一个字符串,字符'('和')'是由自己提供报价的作用。
     -其通常接收HTML参数在函数中使用:$追加(<DIV>)
     -or功能接收CSS选择器:$(DIV>跨度)
     尤其是圆形你注意到一个$全局函数的存在,作为JQuery的,用于选择DOM元素,但有一个稍微好一点的语法,而不需要用引号引起来的字符串参数,聪明的你不觉得!?
自我#列表表达式是一个速记语法$(#列表),自我总是页面,在<html>元素的根元素的引用
 
与sciter.exe前端测试
在现代浏览器,我们有F12工具,使我们能够检查运行的JavaScript代码加载的页面和事件调试的DOM。Sciter相当于这是sciter.exe工具,正如我以前说过。
为了测试我们的前端,通过sciter.exe打开index.html文件从Windows资源管理器中的文件拖放正下降到里面。你会看到“谷歌加载字体..”一个永远站在信息。既然我们没有后台,就永远不会消失。但由于脚本,我们可以很容易模仿,这些2层之间流动的数据。
以下代码是足以模仿调用,将我们的缺失后端被驱动View_OnFontList():

View_OnFontList([
    { family: "Helvetica" },
    { family: "Open Sans" },
    { family: "Consola" }
]);
此代码添加到您的<script>标记的结束,回到sciter.exe,然后按刷新按钮。这就是它。它应该显示与3字体的列表。您可以通过点击“齿轮”按钮,将显示如下窗口检查DOM:
Sciter / HTML / C#基于桌面的应用程序演练
我们可以很容易地看到我们与3 <LI> DOM树表示()给View_OnFontList数据的每个字体的元素。

测试/调试Sciter应用+远程检查HTML

示例应用程序代码现在已完成,所以我们要进行测试和调试/运行完整的可执行文件。
如果有必要,尝试本节之前下载完整的示例应用程序。
 
而在VS调试,确保有打开输出窗口,因为Sciter输出信息到标准输出,其范围从简单的警告,但更重要的是,TIScript执行错误和无法识别的CSS规则(这是最常见的错误,从我的经验发生)。
但它在C#中调试工作,确保实现本机调试所以你会看到在输出窗口Sciter错误信息:项目属性/调试/选中“启用本 地代码调试”

按F5和我们谷歌字体下载应用程序应平稳运行。

在正常的浏览器,我们可以检查你的活泼运行HTML页面(F12工具)的DOM。我们可以通过在inspector.exe工具远程检查我们运行C#程序中Sciter到这一点。

SciterSharp提供了一种简单的方法做这个(你可能想了解涉及的机制在这里)。首先,你需要把inspector.exe的副本,Sciter SDK一旁的主要FontLister.exe可执行文件(完整的示例下载已经拥有它)。然后,在C#中,您只需拨打SciterHost类的DebugInspect()方法:


// Prepares SciterHost and then load the page
var host = new Host();
host.SetupWindow(wnd);
host.AttachEvh(new HostEvh());
host.SetupPage("index.html");
host.DebugInspect();// >-- call it after SetupPage()
..

,它就会打开Sciter检查。有了它打开,在你的程序中,你CTRL + SHIFT +点击任何元素在DOM树中选择它,如下所示:

Sciter / HTML / C#基于桌面的应用程序演练

最重要的事,它工作在Linux中也一样,你需要从SDK沿可执行的二进制加'inspector64“。

4.编译和运行在Linux上

首先,你需要安装单声道和MonoDevelop的在你的Linux系统,所以检查的指示在这里
然后,只需打开MonoDevelop的解决方案,用鼠标右键单击该项目FontListerGTK,单击“设为启动项目”,并尝试建立。希望这将编译原样。
现在,如果你尝试运行,它可能会抛出一个“TypeInitializationException”与内'DllNotFoundException:sciter-gtk-64.so“。这是因为单找不到Sciter DLL(的.so)。您需要安装到Linux环境。最简单的办法就是  下载这个脚本只是(样品.ZIP已经包含在根文件夹该文件),然后:

sudo bash install-libsciter.sh

我面临着Linux的另一个问题是,谷歌网络字体API是抛出异常。希望我找到一个解决办法在这里,是我化险为夷:

Sciter / HTML / C#基于桌面的应用程序演练

附录:Sciter技巧

全局配置

这些是你可以从C#代码Sciter引擎设置一些全局配置:

-SciterX.API.SciterSetOption()API提供了许多选项。一个我有时用的就是改变SCITER_SET_GFX_LAYER选项,让您(在Windows Direct2D的默认设置)设置GFX后端。为什么?因为在旧电脑,发动机经常死机是由于旧的显示硬件/驱动器,这样你就可以做的是切换到非加速GFX模式下,将此选项设置为GFX_LAYER_WARP,它是基于CPU的图像渲染:


SciterX.API.SciterSetOption(IntPtr.Zero, SciterXDef.SCITER_RT_OPTIONS.SCITER_SET_GFX_LAYER, new IntPtr((int) SciterXDef.GFX_LAYER.GFX_LAYER_WARP));
-Another API使你可以添加CSS文件到所有HTML页面的引擎创建。请注意,许多脚本功能创建新的HTML页面,就像view.msgbox(),你不必对这些页面的样式直接控制,所以这个API可能是有用的。
要设定所有页面银的背景下,你会打电话:

string css = "html { background: silver; }";
byte[] bytes = Encoding.UTF8.GetBytes(css);
SciterX.API.SciterAppendMasterCSS(bytes, (uint) bytes.Length);

原生C#DOM操作

在这篇文章中,我们还没有使用它,但SciterSharp库中有通过SciterElement类操作页面的DOM一个完整的API。同样以SciterValue,SciterElement为任何类型的DOM操作的多purpouse类:创建元素,遍历DOM树,改变元件状态/属性/ CSS,等等...

下面是如何在<H1>标题附加到一个页面,并设置它的CSS颜色为蓝色一个简单的例子。
// 获取页面的<body>
var se_body = wnd.RootElement.SelectFirst("body");

// append a <h1>
header to it
se_body.TransformHTML("<h1>Wow, this header was created natively!</h1>", SciterXDom.SET_ELEMENT_HTML.SIH_INSERT_AT_START);

// set <h1>
color to blue
se_body[0].SetStyle("color", "#00F");

TIScript:查看全局数据/通信

期望有时有一种方法来共享不同的HTML页面之间的数据,例如,不同的<帧>的网页,或者甚至做的多个Sciter窗口之间的通信。因为在同一进程Sciter窗口共享相同TIScript VM是可能的。

您可以通过“查看”属性做到这一点。以下分配:

view.CreateAlert = function() {
     self.$append(<div .alert />)
}

..makes的view.CreateAlert()提供全球范围内,所以你可以从任何页面调用它。

你也可以要改为共享数据:


view.standardAlerts = {
     success: "You did it, I knew you could!"
     warning: "Hey, you were advised",
     error: "Huston, we have a problem!"
};

资源加载:通过注射在每一页TIScript内容'sciter:调试peer.tis“

这是一个非常有用的技巧。这种注入TIScript内容到每一个HTML页面的引擎负荷。

首先,你需要确保当您创建SciterWindow,你通过SciterXDef.SCITER_CREATE_WINDOW_FLAGS.SW_ENABLE_DEBUG的则CreateMainWindow()。请注意,如果你调用它只是通过传递窗口的大小,默认情况下,它会得到这个标志,无论如何,所以下面的调用是确定:

wnd.CreateMainWindow(800,600);

SW_ENABLE_DEBUG使您可以使用inspector.exe工具远程检查你的页面。为了做到这一点,发动机注入文件“sciter:调试peer.tis'来加载的所有页面。我们可以通过自定义'sciter:调试peer.tis“的内容,欺骗引擎通过SC_LOAD_DATA通知的处理文件,所以它会加载我们给出TIScript内容,而不是。要做到这一点,在你SciterHost派生类中,添加以下到OnLoadData()方法overrided:

if(sld.uri=="sciter:debug-peer.tis")
{
    string TIScript_content = "function Meow() { stdout.println(1234); }";
    byte[] buffer = Encoding.UTF8.GetBytes(TIScript_content);
    _api.SciterDataReady(_wnd._hwnd, sld.uri, buffer, (uint)buffer.Length);
}

这将使得功能喵()可在全球范围内的所有页面。请注意,您可以添加任何TIScript代码,所以你可以例如,添加,改变页面的DOM功能的代码,或检查与加载页面URL self.url() 并做一些定制的程序。

注意,对于这样它们被描述的替代方法在这里

冷却的东西,你可以做Sciter

可能性是无穷的,在这里我将只是点的东西,你可以在Sciter实现一些链接:

-THE的你可以在SDK的samples /文件夹内的发动机达到灵感的主要来源,这是一个必须退房!

? -你可以写HTML像PHP <PHP回声“无所谓”; ?>在这里,你可以在HTML的中间混合输出的可编程性,请参阅:http://sciter.com/forums/topic/new-page-load-using-tiscript/#post-43481

-通过脚本,你可以自定义/覆盖任何DOM元素在其所有的4步画图纸:背景,内容,前景和大纲,看http://sciter.com/342-2/

结语

这结束了beeing一个很长的文章,即使它涵盖了理解所有参与基于C#Sciter桌面应用程序的作品的要领。希望它是一个读数清晰。
我计划继续我的Sciter教学系列怎么办HTML / CSS动画的Sciter特定方式的教程。也是我下一个主要目标是有OSX /单声道SciterSharp支持,如何在这个平台上使用适当的教程。敬请期待!

.net教程阅读排行

最新文章