- PVSM.RU - https://www.pvsm.ru -
Chromium Embedded Framework (CEF) [1] — это проект с открытыми исходными кодами, созданный в 2008 году как элемент управления Web browser, работающий на базе Chromium от Google.
На данный момент это довольно мощный инструмент для разработки настольных приложений, со списком решений, использующих этот контрол можно ознакомиться здесь [2]. Но достаточно сказать, что его используют такие широко известные продукты, как Evernote и Steam.
Итак, что же дает этот фреймворк?
В общем, все, что позволит Вам сделать свой собственный браузер наподобие google chrome (только зачем?). Но нам он понадобится, для того, чтобы создавать собственные приложения с HTML5/CSS3 интерфейсом и аппаратно ускоренной графикой.
Библиотека chromiumembedded, ссылка на которую давалась в начале статьи, реализована на C++. Но что делать, если Ваше решение уже работает на другом, управляемом языке программирования? Специально для нас существуют обертки для Java, Delphi, Python и .NET. Об использовании библиотеки CefSharp для .NET и пойдет речь.
CefSharp [3] — библиотека-обертка для chromiumembedded. Однако функционал ее несколько уступает по возможностям последней.
Что же нам доступно:
Чего не хватает:
В качестве поощрения можно отметить то, что начать работать с библиотекой можно довольно быстро (при условии, что у вас есть компилированный вариант), а также тот факт, что планка понимания HTML+JS решений ниже, чем у WPF, и для тех, кто боится уходить в многомесячное изучение сложной технологии, можно просто использовать всеми любимый HTML.
Три главные вещи, которые нужны для работы — это локальный обработчик протокола, глобальный объект и тот объект, который будет у нас управлять фреймворком.
Реализуется пара классов: фабрика (реализует интерфейс CefSharp.ISchemeHandlerFactory) и, собственно, сам обработчик (реализующий интерфейс CefSharp.ISchemeHandler).
С первым все понятно:
public class LocalSchemeHandlerFactory : ISchemeHandlerFactory
{
public ISchemeHandler Create()
{
return new LocalSchemeHandler();
}
}
Второй не будет сложнее:
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-файл приложения, можно воспользоваться методом GetStream или GetString класса ResourceManager. Из плюсов — исходный код вашего приложения будет находиться внутри .exe или .dll файла. Из минусов — при изменении js-кода придется каждый раз заново компилировать приложение.
С ним еще проще — это обычный объект, содержащий методы и поля. Один минус — на весь проект у Вас будет по одному экземпляру каждого такого класса.
Я решил сделать класс наследником 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 с формой, его содержащую. Для этого родился некоторого рода жестокий костыль, который я представлю на обозрение публики.
Дабы не захламлять статью лоскутами кода, я приведу некоторые выдержки из листинга.
Он выполняет операцию по вызову из 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% managed парсер. Тоже костыль.
С кодом можете ознакомиться здесь [4].
Автор: Dima_Sharihin
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/16081
Ссылки в тексте:
[1] Chromium Embedded Framework (CEF): http://code.google.com/p/chromiumembedded/
[2] здесь: http://en.wikipedia.org/wiki/Chromium_Embedded_Framework
[3] CefSharp: https://github.com/chillitom/CefSharp
[4] здесь: https://dl.dropbox.com/u/22264454/coding/Example.zip
Нажмите здесь для печати.