前の記事でとりあえ起動まではいったが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(); } } }