文書の過去の版を表示しています。
目次
CefSharp
概要
Chromiumをアプリケーションに組み込むためのフレームワークで、C#実装がCefSharpとなります。
Cef
CefはChromium Embedded Frameworkの略で、Chromiumをアプリケーションに組み込むためのフレームワークです。
https://bitbucket.org/chromiumembedded/cef
Cefには各言語向けのラッパーがあり、その中のC#実装がCefSharpです。
https://github.com/cefsharp/CefSharp
インストール
CefSharpはNuGetでインストールできるようになっている。
WPF対応版とWinForms対応のコンポーネントに分かれている。
.NET Framework 4.5.2以上が必要となる。
Any CPUには対応していないが、プラットフォームをx86かx64を自動で判別する方法がある。
- NuGetでCefSharp.WinFormsをインストールする
- Visual Studioを終了する。
- 対象プロジェクトのcsprojファイルの最初のProperyGroupに末尾に<CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>を追加する
- Visual Studioを起動してプロジェクトを読み込む。
- Debug および Relese フォルダ内に x86 と x64 フォルダが作成される。
- 下記サイトで指定されたプログラムを組み込む。
CefSharpでAnyCPU対応に苦慮した話2
Any CPUで32bit優先にした場合(32bit優先とはARMのWindows環境でも動作可能となる)
How to use CefSharp (chromium embedded framework c#) in a Winforms application
ブラウザ言語を変更する
ひらがなと漢字が混在していた場合、ひらがなのみ太いなどのフォント表示(中国語っぽい)がされてしまう。
原因はロケールが違うため、言語を日本語に変更する。
CefSharp.Wpfのlocaleを変更する - stackoverflow
CefSettings settings = new CefSettings(); settings.Locale = "ja" settings.AcceptLanguageList = "ja-JP" Cef.Initialize(settings);
または、OSのカルチャーを取得してセットする。
CefSettings settings = new CefSettings(); settings.Locale = System.Globalization.CultureInfo.CurrentCulture.Parent.ToString(); settings.AcceptLanguageList = System.Globalization.CultureInfo.CurrentCulture.Name; Cef.Initialize(settings);
GPUCacheやblob_storageがデスクトップに作成される
CefSharpを使用したアプリケーションをデスクトップのショートカットから実行した場合
ショートカットの作業フォルダが空だった場合、GPUCacheがblob_storageフォルダがデスクトップに作成されてしまう。
対応として作業フォルダを指定することで、作業フォルダ側に作成される。
ショートカットの作業フォルダ対応ではなくプログラムで対応する場合
カレントフォルダを設定しただけでは、GPUCacheフォルダはカレントフォルダに作成されるが、blob_storageフォルダはデスクトップに作成されてしまう。
対応として、CefSettings.UserDataPath にカレントフォルダを指定する必要がある。
// カレントディレクトリをアプリケーション起動パスに設定する string appPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); Directory.SetCurrentDirectory(appPath); CefSettings settings = new CefSettings(); settings.UserDataPath = appPath; Cef.Initialize(settings);
Cef.Initializeの設定は1回のみ
Cef.Initializeの設定は1回のみで、new ChromiumWebBrowser する前に設定する。
Cef.Initialize したかどうかは、Cef.IsInitialized で判断(false:未設定、true:設定済)する。
C# (CSharp) CefSettings Code Examples
パネル配下にブラウザをセット
フォームにToolboxを配置したあったので、パネルを用意して配下にブラウザをセットした。
browser = new ChromiumWebBrowser("https://www.google.co.jp/"); this.pnlWebBrowser.Controls.Add(browser); browser.Dock = DockStyle.Fill;
URL(アドレス)の取得
WinFormsの場合
Addressプロパティが見当たらないため、アドレス変更イベントで変数にセットする。
this.browser= new ChromiumWebBrowser(); this.browser.AddressChanged += browser_AddressChanged; private void browser_AddressChanged(object sender, AddressChangedEventArgs e) { this.CurrentAddress = e.Address; }
WPFの場合
Addressプロパティで取得できる。
var browser = new CefSharp.Wpf.ChromiumWebBrowser(); this.CurrentAddress = browser.Address
URL(アドレス)の変更
WinFormsの場合
Addressプロパティが見当たらないため、Loadメソッドで変更する。
How to change the URL using CefSharp WinForms - stackoverflow
this.Browser = new ChromiumWebBrowser(); this.Browser.Load("https://www.google.co.jp/")
WPFの場合
Addressプロパティ または、Loadメソッドで変更する。
WPFでCefSharp(Chromiumの.NET向け実装)を使う - 1
var browser = new ChromiumWebBrowser(); browser.Address = "https://www.google.co.jp/";
AddressプロパティとLoadメソッドでは、基本的な挙動に変わりはありませんが、ブラウザが初期化されていないときに実行すると挙動が変わる。
Addressを書き換えた場合
ブラウザの初期化後にそのURLに遷移する
Loadを呼んだ場合
初期化されていないので何も起こらない
ブラウザ読込完了時イベント
IEのWebブラウザコンポーネントにあった DocumentCompleted イベントの代わり。
CefSharp documentcompleted - stackoverflow
var browser = new ChromiumWebBrowser(); browser.LoadingStateChanged += OnLoadingStateChanged; private void OnLoadingStateChanged(object sender, LoadingStateChangedEventArgs e) { if (!e.IsLoading) { // 読込完了処理を記述 } }
HTML要素のボタンをClickする
Javascriptで操作させてボタンをClickさせる。
ExecuteScriptAsyncメソッドで、Javascriptを実行する。
var browser = new ChromiumWebBrowser(); // Enterボタンクリック用スクリプト string clickScript = "var inputs = document.getElementsByTagName('input');" + "for(var i = 0; i < inputs.length; i++){ " + " if(inputs[i].getAttribute('value') == 'Enter') inputs[i].click(); " + "}"; string jsScript = string.Format("document.getElementById('c03').value = '{0}';", txtInput.Text); browser.ExecuteScriptAsync(jsScript + clickScript);
HTML要素の値を取得する
Javascriptで操作させて取得する。
ExecuteScriptAsyncメソッドで、Javascriptを実行する。
CefSharp - HTML要素の値を取得する
var browser = new ChromiumWebBrowser(); browser.EvaluateScriptAsync(jsScript).ContinueWith(x => { var response = x.Result; if (response.Success && response.Result != null) { userCodeData = response.Result.ToString(); } });
キー押下の処理
IEのWebブラウザコンポーネントにあった previewkeydown イベントの代わり
KeyboardHandleクラスを定義する。
public class KeyboardHandler : IKeyboardHandler { private frmMain _frm; public KeyboardHandler(frmMain frm) { _frm = frm; } public bool OnKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey) { return false; } public bool OnPreKeyEvent(IWebBrowser browserControl, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut) { _frm.OnPreviewKeyDown(windowsKeyCode, modifiers); return false; } }
今回は、Enterキー押下時のみ処理を行う。
var browser = new ChromiumWebBrowser(); // キーイベント処理登録 browser.KeyboardHandler = new KeyboardHandler(this); public void OnPreviewKeyDown(int windowsKeyCode, CefEventFlags modifiers) { if (windowsKeyCode != (int)Keys.Return) return; // Enterキー押下時の処理を記述する。 }
フォーカスのセット
何故か、browser.Focus() ではフォーカスがセットされなかったため、Win32APIのSetFocusを使用した。
読み込み完了時のイベントで処理している。
// フォーカスセット用 [DllImport("user32.dll", SetLastError = true)] static extern IntPtr SetFocus(IntPtr hWnd); var browser = new ChromiumWebBrowser(); browser.LoadingStateChanged += OnLoadingStateChanged; private void OnLoadingStateChanged(object sender, LoadingStateChangedEventArgs e) { if (String.IsNullOrEmpty(this.CurrentAddress)) return; if (e.IsLoading) return; // 読込完了時にWebブラウザにフォーカスをセット this.Invoke((MethodInvoker)delegate { SetFocus(browser.Handle); }); }
最初は、ブラウザにマウスクリックするとフォーカスがセットされたのでマウスクリックするプログラムを組んだが、SetFocusで出来たのでやめた。
[DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)] static extern void SetCursorPos(int X, int Y); [DllImport("USER32.dll", CallingConvention = CallingConvention.StdCall)] static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo); private void SetFocusWebBrowser() { // マウス位置を移動してクリックして元に戻す this.Invoke((MethodInvoker)delegate { int curX = Cursor.Position.X; int curY = Cursor.Position.Y; var point = this.pnlWebBrowser.PointToScreen(this.pnlWebBrowser.Location); SetCursorPos(point.X, point.Y); mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); SetCursorPos(curX, curY); }); }