前の記事でとりあえ起動まではいったがCEFの.NETとJavaScriptの呼び出し合いを引き続き確認していた。
とりあえずブラウザで表示させるコンテンツを作成した。
html-resourcesというフォルダを作成してコンテンツとしてビルドしたらコピーされるように設定した。(Basercmsの都合で左が切れてしまっている)
index.htmlは以下のようにした。
<html>
<head>
<link type="text/css" rel="stylesheet" href="../css/jquery-ui.min.css" />
<script type="text/javascript" src="../js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../js/jquery-ui.min.js"></script>
<style>
#progressbar {
margin-top: 10px;
margin-bottom: 10px;
}
.ui-progressbar {
position: relative;
}
.progress-label {
position: absolute;
left: 50%;
top: 4px;
font-weight: bold;
font-size:22px;
text-shadow: 1px 1px 0 #fff;
}
</style>
<script>
var progress = 0;
$(function() {
$("#progressbar").progressbar({
value: 0,
max: 1024
});
$("#btn1").click(function() {
cefCustomObject.text("CefSharp sample UI");
});
$("#btn2").click(function() {
cefCustomObject.close();
});
});
</script>
</head>
<body style="background-color:transparent;">
<h1 style="font-family:Arial">TEST GUI SAMPLE</h1>
<div>
<button id="btn1" class="ui-button ui-widget ui-corner-all">Set Title</button>
<button id="btn2" class="ui-button ui-widget ui-corner-all">Close</button>
</div>
<div id="progressbar"><div id="label" class="progress-label"></div></div>
</body>
</html>
そのうえでMainWIndow.xaml.csは以下のようにする。
これで定期的にJavaScript側のprogressという変数はcount % 1024に置き換えられ,progressbarの更新が行われる。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CefSharp;
using CefSharp.Wpf;
using System.Windows.Threading;
namespace WPFwebui
{
public partial class MainWindow : Window
{
// 実行ファイルのディレクトリ取得
public string StartupPath {
get {
return System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(Environment.GetCommandLineArgs()[0]));
}
}
// Chrrmiumに見せるオブジェクト
CefCustomObject exposedObj = null;
CefSharp.Wpf.ChromiumWebBrowser browser;
public MainWindow()
{
InitializeComponent();
browser = new CefSharp.Wpf.ChromiumWebBrowser();
// アドレスの取得
String page = string.Format(@"{0}\html-resources\html\index.html", StartupPath);
BrowserSettings browserSettings = new BrowserSettings();
browserSettings.FileAccessFromFileUrls = CefState.Enabled;
browserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings = browserSettings;
// アドレス設定
browser.Address = page;
Content = browser;
browser.Loaded += BrowserLoaded;
// 例1: Chromiumに.NETオブジェクトを露出
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
exposedObj = new CefCustomObject(browser, this);
browser.RegisterJsObject("cefCustomObject", exposedObj);
}
// 例2: .NET から定期的にスクリプト実行の例(前半)
private DispatcherTimer timer1 = null;
void BrowserLoaded(object sender, EventArgs e)
{
timer1 = new DispatcherTimer(DispatcherPriority.Normal);
timer1.Interval = new TimeSpan(0, 0, 0, 0, 100);
timer1.Tick += new EventHandler(Timer1_Tick);
timer1.Start();
}
// .NET から定期的にスクリプト実行の例(後半)
private Int64 count = 0;
void Timer1_Tick(object sender, EventArgs e)
{
this.browser.ExecuteScriptAsync(
"progress = " + count % 1024 + ";" +
"$('#progressbar').progressbar({value: progress,max: 1024});" +
"$('#label').html(progress);");
count++;
}
}
}
例えばCef側に露出させる.NETオブジェクトの例は以下のようにする。
これでJavaScript側でボタン1を押すとtext()が実行されMainWindowのタイトルが変更される。ボタン2を押すとclose()が実行される。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;
using CefSharp.Wpf;
using System.Diagnostics;
using System.Windows;
namespace WPFwebui
{
public class CefCustomObject
{
private static ChromiumWebBrowser _instanceBrowser = null;
private Window _window = null;
public CefCustomObject(ChromiumWebBrowser originalBrowser, Window window)
{
_instanceBrowser = originalBrowser;
_window = window;
}
delegate void TextDelegate(string _text);
public void text(string _text)
{
if (!_window.Dispatcher.CheckAccess())
{
_window.Dispatcher.Invoke(new TextDelegate(text), new object[]{ _text });
return;
}
_window.Title = _text;
}
delegate void CloseDelegate();
public void close()
{
if (!_window.Dispatcher.CheckAccess())
{
_window.Dispatcher.Invoke(new CloseDelegate(close));
return;
}
_window.Close();
}
}
}