Sciter/HTML/C#でマルチプラットフォームなデスクトップアプリ

# sciter
[sciter – HTML/CSS UI Engine](http://sciter.com/)

> Embeddable HTML/CSS/script engine
> for modern UI development

CefSharpやElectronみたいな感じ。
ただし、Chromiumを使用しているわけではなくデスクトップアプリに特化したエンジンを使用している。

コア部分がOSSではないのがちょっと残念。
各言語向けのSDKはGitHub上で公開されている。
[SDK bindings / sciter](http://sciter.com/developers/sciter-sdk-bindings/)

## 特徴
### クロスプラットフォーム
WindowsでもLinuxでもMacでも動く。

### 多言語対応
C APIを利用して任意の言語で書ける。（C++/Delphi/D/Go/C#...）

### HTML/CSS/script
HTML、CSS、javascript知ってればかけるよ！
ただし、HTML5、CSS3に完全に対応しているわけではない。
scriptもjsライクなTIScriptというものを使う。
（あくまでデスクトップアプリのUIエンジンなので必要が無いということだろう）

### その他
ICQのクライアントやNortonやAvastなどのUIに採用されている。（なぜかセキュリティソフト系に強いみたい）

## ライセンス
静的リンクするにはお金が必要。
[Licensing & prices / sciter](http://sciter.com/prices/)

### 無料ライセンス
公開されているバイナリを自己責任で使う分には商用でも無料みたい。（詳しいライセンスについてはSDKに含まれるライセンスファイルを参照）


その他、詳しいことは[公式サイト](http://sciter.com/)参照のこと。

## SciterSharp
[midiway/SciterSharp: Port of Sciter headers for the C# language](https://github.com/midiway/SciterSharp)
> Cross-platform Sciter bindings for .NET
This library provides bindings of Sciter C/C++ headers to the C# language. Sciter is a multi-platform HTML engine. With this library you can create C#.NET desktop application using not just HTML, but all the features of Sciter: CSS3, SVG, scripintg, AJAX,... Sciter is free for commercial use.

こいつがSciterとC#(.NET)をつなぐ。
ライセンスは`GNU GPL v3`。

# 動かしてみよう
## 環境
- Windows10
- VisualStudio 2015
- Ubuntu 14.04

## 準備
以下のサイトでテンプレートをダウンロード
[Sciter Bootstrap · MI Software](http://misoftware.rs/Bootstrap/Download)

![sciter_01.JPG](https://qiita-image-store.s3.amazonaws.com/0/54591/626a2de1-5668-c4a5-465a-7cd66a5be232.jpeg)

0. `Windows 32-64bits and MONO/GTK 64bits / Visual Studio or MonoDevelop >= 5.10 / C#`を選択
0. `Multi-platform template`を選択
0. プロジェクト名を入力
0. ダウンロード

## コードを見てみる
0. zipファイルを解凍
0. VS2105でソリューションを開いてみる

![sciter_02.png](https://qiita-image-store.s3.amazonaws.com/0/54591/1a4f9152-12eb-95f3-2257-718e93b53fb1.png)

### Windows/GTK
初期化処理とアイコンの扱いが違うくらいかな。

```csharp:Program.cs
static void Main(string[] args)
{
#if WINDOWS
	// Sciter needs this for drag'n'drop support; STAThread is required for OleInitialize succeess
	int oleres = PInvokeWindows.OleInitialize(IntPtr.Zero);
	Debug.Assert(oleres == 0);
#endif
#if GTKMONO
	PInvokeGTK.gtk_init(IntPtr.Zero, IntPtr.Zero);
#endif

	
	// Create the window
	/*
		NOTE:
		In Linux, if you are getting a System.TypeInitializationException below, it is because you don't have 'libsciter-gtk-64.so' in your LD_LIBRARY_PATH.
		Run 'sudo bash install-libsciter.sh' contained in this package to install it in your system.
	*/
	var wnd = new SciterWindow();
	wnd.CreateMainWindow(1500, 800);
	wnd.CenterTopLevelWindow();
	wnd.Title = "Sciter Bootstrap";
#if WINDOWS
	wnd.Icon = Properties.Resources.IconMain;
#endif

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

	// Show window and Run message loop
	wnd.Show();
	PInvokeUtils.RunMsgLoop();
}
```

### Debug/Release
デバッグ時はリソース（htmlファイル等）を直接読み込み、リリース時はコンパイルの段階でリソースをバイト配列として静的な変数に格納し、実行時に呼び出している。

```csharp:Host.cs
...
public BaseHost()
{
#if !DEBUG
	_archive.Open(SciterSharpAppResource.ArchiveResource.resources);
#endif
}

public void SetupWindow(SciterWindow wnd)
{
	_wnd = wnd;
	SetupCallback(wnd._hwnd);
}

public void SetupPage(string page_from_res_folder)
{
#if DEBUG
	string path = Environment.CurrentDirectory + "/../../res/" + page_from_res_folder;
	Debug.Assert(File.Exists(path));
	path = path.Replace('\\', '/');

	string url = "file:///" + path;
#else
	string url = "archive://app/" + page_from_res_folder;
#endif

	bool res = _wnd.LoadPage(url);
	Debug.Assert(res);
}
...
```

## 動かしてみる
`Host_HelloWorld`メソッドの戻り値を`h1`に、Sciterのバジョン情報を`h2`に出力している

![sciter_03.png](https://qiita-image-store.s3.amazonaws.com/0/54591/455de162-ceda-6163-ceaf-2b7eada2660e.png)

### HTML

```html:index.html
<html>
<head>
	<style>
		h1 { color: blue; font-size: 30px; }
	</style>

	<script type="text/tiscript">
		$(h1).text = view.Host_HelloWorld();

		var version_major = Sciter.VERSION >> 16;
		var version_minor = Sciter.VERSION & 0xFFFF;
		var revision_major = Sciter.REVISION >> 16;
		var revision_minor = Sciter.REVISION & 0xFFFF;
		$(h2).text = "Sciter version: " + String.printf("%x.%x.%x.%x", version_major, version_minor, revision_major, revision_minor);
	</script>
</head>

<body>
	<h1 />
	<h2 />
</body>
</html>
```

### C# 

```csharp:Host.cs
...
class HostEvh : SciterEventHandler
{
	protected override bool OnScriptCall(SciterElement se, string name, SciterValue[] args, out SciterValue result)
	{
		switch(name)
		{
			case "Host_HelloWorld":
				result = new SciterValue("Hello World! (from native side)");
				return true;
		}

		result = null;
		return false;
	}
}
...
```

## Linuxで動かしてみる
### 準備
- Mono、MonoDevelopのインストール
[Install Mono on Linux | Mono](http://www.mono-project.com/docs/getting-started/install/linux/#debian-ubuntu-and-derivatives)
- gcc 4.9のインストール
[c++ - version `CXXABI_1.3.8' not found (required by ...) - Stack Overflow](http://stackoverflow.com/questions/23494103/version-cxxabi-1-3-8-not-found-required-by)
- ダウンロードしたプロジェクトのルートにある`install-libsciter.sh`を実行

### 実行
xbuildからビルドしたバイナリはなぜか落ちる。
ので、MonoDevelopでビルドし、
```
mono SciterTest.exe
```

![sciter_04.png](https://qiita-image-store.s3.amazonaws.com/0/54591/43187c3b-184c-45ef-7d12-8c1c43fd9fb3.png)

# まとめ
- C#とさくっと連携
- マルチプラットフォーム
- Electron等と比べライブラリが軽い

## 参考
[Sciter/HTML/C# based desktop apps walkthrough - CodeProject](http://www.codeproject.com/Articles/1057199/Sciter-HTML-Csharp-based-desktop-apps-walkthrough)
[Sciter - multiplatform embeddable HTML/CSS/scripting UI engine - CodeProject](http://www.codeproject.com/Articles/859098/Sciter-multiplatform-embeddable-HTML-CSS-scripting)