Chromium Embedded Frameworkと.NETの最初のステップ

Chromium Embedded Framework(CEF)は、GoogleのChromiumを搭載したWebブラウザコントロールとして2008年に作成されたオープンソースプロジェクトです。

現時点では、これはデスクトップアプリケーションを開発するための非常に強力なツールです 。このコントロールを使用したソリューションのリストは、 ここにあります 。 しかし、EvernoteやSteamなどの有名な製品で使用されていると言えば十分です。



このフレームワークは何を提供しますか?





一般に、Google Chromeのような独自のブラウザを作成できるすべてのもの(しかし、なぜですか?)。 ただし、HTML5 / CSS3インターフェースとハードウェアアクセラレーショングラフィックスを使用して独自のアプリケーションを作成するために必要になります。



そして今、悲しいことについて



記事の冒頭に記載されているリンクが埋め込まれたchromiumembeddedライブラリは、C ++で実装されています。 しかし、ソリューションが別の制御されたプログラミング言語で既に機能している場合はどうでしょうか? 特に、Java、Delphi、Python、および.NETのラッパーがあります。 .NET用のCefSharpライブラリの使用について説明します。



CefSharpに会う


CefSharpは、 chromembeddedのラッパーライブラリです。 ただし、その機能は後者の機能においてやや劣っています。

利用可能なもの:

  1. WebViewクラスコンポーネントを無制限に作成
  2. ページ読み込みイベント、ナビゲーションイベントの処理
  3. カスタムプロトコルハンドラー。
  4. ページ実行時のJsコードインジェクション
  5. 静的メソッドを使用したグローバル[ネイティブコード]オブジェクトの作成


不足しているもの:

  1. 通常のイベントモデル。 いいえ、真剣に、これは.NETライブラリのようには見えません。

    public Window(string Url, CefSharp.BrowserSettings settings = null) { // ... _Browser = new WebView(Url, settings ?? new CefSharp.BrowserSettings { DefaultEncoding = "UTF-8" }); _Browser.PropertyChanged += _Browser_PropertyChanged; // ... } void _Browser_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName == "IsBrowserInitialized" && !isInitialized) doSomeStuff(); //   }
          
          







  2. WebViewクラスの異なるインスタンスにさまざまなオブジェクトを埋め込みます。 誰でも絶対に登録済みのメソッドを呼び出すことができるという事実に同意する必要があります
  3. CLRからJSへ、またはその逆への型変換。 この問題を視覚的に解決するための松葉杖についてさらに説明します。
  4. 呼び出されたメソッドを、WebViewが配置されている特定のフォームに関連付けることはできません。
  5. マイナスではありませんが、CefSharpをコンパイルする環境はVisual Studio 2008である必要があります。


推奨事項として、ライブラリの操作を非常に迅速に開始できることに注意してください(コンパイルされたバージョンがある場合)。また、HTML + JSソリューションの理解レベルがWPFのレベルよりも低いこと、および複雑な技術を何ヶ月も勉強することを恐れて、あなたの好きなHTMLを簡単に使うことができます。



最初の知り合い



作業に必要な3つの主なものは、ローカルプロトコルハンドラー、グローバルオブジェクト、およびフレームワークを管理するオブジェクトです。



ローカルプロトコルハンドラー


いくつかのクラスが実装されています:ファクトリー(CefSharp.ISchemeHandlerFactoryインターフェースを実装)と、実際には、ハンドラー自体(CefSharp.ISchemeHandlerインターフェースを実装)。

最初のものでは、すべてが明確です:

  public class LocalSchemeHandlerFactory : ISchemeHandlerFactory { public ISchemeHandler Create() { return new LocalSchemeHandler(); } }
      
      





2番目は難しくありません:

  public class LocalSchemeHandler : ISchemeHandler { //     ,      ,      public bool ProcessRequest(IRequest request, ref string mimeType, ref Stream stream) { //  IRequest     //  mimeType    MIME- .  ,  Chromium    text/javascript  text/plain  image/png //  Stream   ,   - MemoryStream ,           return true; //     .  false } }
      
      





アプリケーションのjsファイルを含めるには、ResourceManagerクラスのGetStreamまたはGetStringメソッドを使用できます。 プラス-アプリケーションのソースコードは、.exeまたは.dllファイル内に配置されます。 マイナスの点-js-codeを変更するときは、毎回アプリケーションを再コンパイルする必要があります。



.NETとJS間のブリッジオブジェクト


さらに簡単です-メソッドとフィールドを含む通常のオブジェクトです。 1マイナス-プロジェクト全体で、そのようなクラスのコピーが1つあります。



CEFの初期化


クラスをApplicationContextの後継にすることにしました。 ウィンドウ表示の場合、WinFormsはより高速に実行され、WPFをドラッグする必要はありません。

  public class ApplicationController : ApplicationContext { protected Dictionary<string, object> registeredObjects; public ApplicationController(CefSharp.Settings settings = null) { registeredObjects = new Dictionary<string, object>(); string resources = Path.Combine(Directory.GetCurrentDirectory(), "cache"); if (Directory.Exists(resources)) Directory.CreateDirectory(resources); CefSharp.CEF.Initialize(settings ?? new CefSharp.Settings() { Locale = "ru", CachePath = resources }); CefSharp.CEF.RegisterScheme("local", new LocalSchemeHandlerFactory()); registerJsObject("Form", new WindowObject()); //     -. } public void registerJsObject(string Name, object Object) { if (!registeredObjects.ContainsKey(Name)) { registeredObjects.Add(Name, Object); CefSharp.CEF.RegisterJsObject(Name, Object); } } }
      
      







これで、実際には、すべてです。 フォームを作成し、それにWebViewコンポーネントを追加して、好きなように作業できます。

あなたがこの場所まで読んだことがあるなら、あなたは忍耐強い人であり、私はあなたに感謝しています。



しかし、これは私たちにとって十分ではありません



前述したように、CefSharpにはいくつかの欠陥があります。 たとえば、WebViewコンポーネントを含むフォームに関連付けることはできません。 このために、ある種の残酷な松葉杖が誕生しました。それを一般公開します。

コードの断片で記事を散らかさないために、リストからいくつかの抜粋を提供します。



1フォームから継承した新しいウィンドウクラス






2共通のCall Bridgeオブジェクト


JSからC#への呼び出し操作を実行します。

 public class WindowObject { public string Invoke(string Id, string Method, string JSONData) { object x = JSON.JsonDecode(JSONData); if (x is ArrayList) { ArrayList y = (ArrayList)x; object[] args = new object[y.Count]; for (var i = 0; i < args.Length; i++) args[i] = y[i]; return JScripter.CreateString(Window.JSInvoke(Id, Method, args)); } else return JScripter.CreateString(Window.JSInvoke(Id, Method, new object[] { x })); } public void Close(string Id) { Window.FormEnumerator.getWindow(Id).Close(); } }
      
      





注意深い読者は、何かが間違っていることに気付くでしょう。通常のオブジェクトの代わりに、CefSharpでは、int、double、bool、stringなどの単純な型のみを交換できます。 しかし、実際には、通常は正反対です。 したがって、この松葉杖はJSONでデータのパッキング/アンパッキングを使用します。 解決策は不完全で、無駄な時間がかかりますが、これらはライブラリの制限です。

DataContractJsonSerializerは特定のタイプでのみ機能するため、使用するには問題があります。 そのため、プロジェクトでは100%マネージパーサーを使用しました。 松葉杖も。



ここでコードを見つけることができます。



All Articles