本文介绍了如何通过C#使用Sciter通过使用创建基于HTML的桌面应用程序SciterSharp库(.NET绑定过Sciter API)。为了快速启动我们的应用程序,我们使用一个Sciter引导模板,这有助于使我们的跨Windows和Linux应用程序编译。
- < - >为UI的本地集成主机通讯,DOM操作,资源跟踪,所有通过C#
- 量好CSS3与使用Flex单位一个漂亮的布点系统
- 通过TIScript语言脚本(JavaScript的扩展)
- 一个脚本API的前端级DOM /风格操作,AJAX调用,JSON,...
这也是免费用于商业用途,虽然它不是开源。它分布作为你的C / C ++ SDK内找到本机共享库(DLL)。该SDK包含用于构建Windows,Linux和OSX。
Sciter技术在现实世界中的一些大的软件使用,证明多远,你可以去用它:ICQ客户端,诺顿,停住下,BitDefender,ESET杀毒软件。
该示例桌面应用程序使用“ 谷歌API客户端库.NET ”查询谷歌的字体 用于显示用户可用的字体列表和一个按钮来下载它们。这将需要本地C#编码以及HTML和脚本,用于使用户界面,以及该2层之间进行通信的混合。这样,您将获得如何创建一个位本机C#编码的应用涉及熟悉,并与异步资源加载,并在如何通过UI /原生层之间的数据。完整的源代码也可在GitHub上。
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的缺点
- 这不是一个所见即所得的环境类似的WebForms或WPF,你需要写HTML代码和预览造成视觉的sciter.exe工具(当然,如果你认为HTML是一个很好的方法,在所见即所得那么它真的不是一个劣势)
- 缺乏HTML5的功能和W3C标准:不能简单地抓取像jQuery或引导图书馆和Sciter使用
- Linux的/ GTK支持有许多HTML / CSS缺失的功能,如果相比于Windows的版本,这是比较成熟的; 我没有测试OSX支持,因为我不拥有一台苹果机=(但据说是因为在Windows中一样好
1.入门
要开始,你心里一定有什么,我们将在本文中实现和所涉及的目标:
所以上手,我们需要获得一些资源,因此遵循以下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包:为的Windows或MONO / GTK + 3
-Or下载从整个项目https://github.com/midiway/SciterSharp ; 我强烈建议这样做,因为这样的话,你可以调试和步骤在SciterSharp代码,看看它在做什么,这是一个非常小的项目呢
然而,这些方法不支持这篇文章,因为我们要开始Sciter引导模板代码,因为它是多平台的准备,我们希望我们的应用程序在Windows和Linux上运行。
安装的NuGet包,并获得谷歌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.代码手 - >后端
窗口创建
// 创建窗口
var wnd = new SciterWindow();
wnd.CreateMainWindow(800, 600);
wnd.CenterTopLevelWindow();
wnd.Title = "Font Lister";
wnd.LoadHtml("<html><body>Hello World!</body></html>");
wnd.Show();
网页托管解释
// 准备SciterHost然后加载页面
var host = new Host();
host.SetupWindow(wnd);
host.AttachEvh(new HostEvh());
host.SetupPage("index.html");
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; }
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); ...
...
// 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(); }
public static void DownloadFont(string family, string savefolder) { ... }
ZipFile.CreateFromDirectory(tmppath, savefolder + "/" + family + ".zip");

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;
}
引用:在TIScript,只要您拨打“视图”变量的方法,而这个功能的方法是不确定的,Sciter引擎调用连接到您的SciterHost OnScriptCall()事件处理程序,给它一个机会来处理不存在的函数名。如果从返回'真'OnScriptCall处理程序,这意味着你处理呼叫和脚本虚拟机将不会触发“视图(View([对象视图]))没有方法- Host_DownloadFont”异常并停止执行脚本。
..
FontLister.Data.GAPI.Setup();
..
.. Program.HostInstance.CallFunction( “ View_OnFontList”,SV); // - >断点这里 ..
Program.HostInstance.CallFunction("View_OnFontList", sv);// line 46 Program.HostInstance.EvalScript("view.Host_DownloadFont(\"D:/\", \"Open Sans\", function(res) {})");// line 47

3.代码手 - >前端
现在我们正在进入发展的一个全新的领域其中涉及纯HTML / CSS和脚本与TIScript语言。我可能会说这是比后端更容易,只要你有一点HTML和CSS的经验。即使你是在网络技术方面的专家,这是值得阅读本节,因为在Sciter HTML / CSS的支持有一些细微之处并非由标准的浏览器支持。TIScript拥有标准的JS很多差异,但它仍然一个Javascript语言一样。
<html>
<head>
</head>
<body>
<div .warning>Loading Google fonts..</div>
<div #list />
</body>
</html>
list-of-details
{
display: block;// or inline, inline-block, ..
}
<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>
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功能:
View_OnFontList([
{ family: "Helvetica" },
{ family: "Open Sans" },
{ family: "Consola" }
]);

测试/调试Sciter应用+远程检查HTML
按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树中选择它,如下所示:
最重要的事,它工作在Linux中也一样,你需要从SDK沿可执行的二进制加'inspector64“。
4.编译和运行在Linux上
sudo bash install-libsciter.sh
我面临着Linux的另一个问题是,谷歌网络字体API是抛出异常。希望我找到一个解决办法在这里,是我化险为夷:

附录: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));
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,等等...
// 获取页面的<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);
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/