装一手,比较简单的英语
It is a lightweight .NET wrapper around the Chromium Embedded Framework (CEF) by Marshall A. Greenblatt. About 30% of the bindings are written in C++/CLI with the majority of code here is C#. It can be used from C# or VB, or any other CLR language. CefSharp provides both WPF and WinForms web browser control implementations.
CefSharp is BSD licensed, so it can be used in both proprietary and free/open source applications. For the full details, see the LICENSE file.
自己总结的:
CefShar 是一个提供了 Chromium Embedded Framework (CEF) 的. NET 接口的开源项目,提供了 Winform、WPF 封装,可以用来代替微软的 WebBrowser,浏览网页,尤为强大的是实现了 C#、VB 等 vs 支持的语言与 JavaScript 的交互方法。
我的开发环境 vs2013、.net4.0,Nugget 中搜索 CefSharp 显示的版本是 v53,然而
的 Breaking Changes 里面有这么一句
- v51.0.0-pre01
不想安装. net4.5.2,所以只能通过
手动命令行导入版本 v49。0.1 的,输入命令
- 工具-程序包管理器-程序包管理控制台
回车等待执行完成,我这里已经安装过了。
- Install-Package CefSharp.WinForms -Version 49.0.1
其他版本命令请参考.
等待导入成功,生成一下... 报错...
嗯?!!!
如果你以为只是在
改为 x86 就太天真了.... 反正我试了不行... 正确的姿 zhi 势 shi:
- 项目名右击-属性-生成-目标平台
,右边平台选择 x86 或 x64,什么?选不到?
- 解决方案名右击-属性-配置属性-配置
下拉
- 配置管理器-活动解决方案平台
,x86/x64 随便选,回来这边下拉已经可以选择了,完事左下角确定,再生成一下试试吧
- 新建
对照下面在一个 Form 的对应位置添加代码
- using CefSharp.WinForms;
- public partial class Form1 : Form
- {
- ChromiumWebBrowser webBrower = null;
- public Form1()
- {
- InitializeComponent();
- Load += Form_Load;
- }
- private void Form_Load(object sender, EventArgs e)
- {
- string path = "www.baidu.com";
- webBrower = new ChromiumWebBrowser(path);
- webBrower.Dock = DockStyle.Fill;//填充方式
- this.Controls.Add(webBrower);
- }
- }
直接运行就 OK 了
把 path 改为 File 协议就行,例如:显示程序下的文件夹 html 中的 test.html
- //获取文件的物理路径
- string path = AppDomain.CurrentDomain.BaseDirectory + "\\html\\test.html";
- //转换为File协议路径
- path = "file://" + path.Replace("\\", "/");
如果实在不知道怎么写的话,建议直接用浏览器把 html 打开,地址栏里面显示的 file:// 链接就是 File 协议路径
推荐个 CCS3 动画的 html, 直接右击保存到本地就行了, 修改完成,同样运行就可以看到页面了,运行还是挺流畅的.
走弯路后的说明:BoundObject 等这三个类以及里面的方法都是可以自己任意定义实现的,和普通的方法类没有太大区别,没有必要去源码中拷过来.
从源码的
中找到三个类 BoundObject、SubBoundObject、ExceptionTestBoundObject 的源码拷过来,记得对应着自己的项目把命名空间名改了。
- CefSharp.Example
如果是. net4.0,TestCallback、TestCallbackException 两个方法有提示 async/await、Task.Run 的报错,处理方式:
. 如果和我一样提示 Nuget 版本 2.7 太低、至少需要 2.8 的,需要卸载升级 Nuget,步骤:
- Install-Package Microsoft.Bcl.Async
, 然后会提示重启,不自动重启的话可以自己手动重启
- VS-〉打开菜单"工具"-"扩展管理器"-〉选择"NuGet Package Manager"-〉点击"卸载"
我这里选择不升级. net 4.5 后面一种方法,同时安装 Microsoft.Bcl.Async.
这里实现的是一个延时回调的例子,即点一个按钮,调用绑定的 C# 方法在 3 秒后显示一条消息同时调用 js 方法立即显示一条消息。 测试内容准备:
- using (javascriptCallback)
- {
- //NOTE: Classes are not supported, simple structs are
- var response = new CallbackResponseStruct("This callback from C# was delayed " + taskDelay + "ms");
- await javascriptCallback.ExecuteAsync(response);
- }
- });
- */
- }
可以运行一下了,点击一下
- <p>
- Javascript Callback Test
- </p>
- <script type="text/javascript">
- function callback(s) {
- var result = document.getElementById('show');
- result.innerText += "callback返回值:" + s.toString() + " 时间:" + Date();
- }
- function TestCallback() {
- //调用后台C#方法TestCallback,返回结果回调方法callback
- bound.TestCallback(callback);
- var result = document.getElementById('show');
- result.innerText = "方法返回 时间: " + Date() + "\n";
- //window.location.assign("http://www.baidu.com");
- }
- </script>
- <button onclick="TestCallback()">
- TestCallBakck
- </button>
- <br />
- <span id="show">
- </span>
按钮,会首先显示一行内容与时间,3 秒后显示第二行内容.
- TestCallBakck
准备内容:
- public string Repeat(string str, int n)
- {
- string result = String.Empty;
- for (int i = 0; i < n; i++)
- {
- result += str;
- }
- return result;
- }
执行结果
- <p>
- 带参数调用C# repeat方法
- </p>
- <span id="content">
- </span>
- <script type="text/javascript">
- var result = bound.Repeat("hello ", 6);
- document.getElementById("content").innerHTML = "" + result + "";
- </script>
这里将一个方法 ReturnJsonEmployeeList 作为参数进行传递,并返回一个 json 数据进行解析展示
- public string ReturnJsonEmployeeList()
- {
- return "{\"employees\":[{\"firstName\":\"John\", \"lastName\":\"Doe\"},{\"firstName\":\"Anna\", \"lastName\":\"Smith\"},{\"firstName\":\"Peter\", \"lastName\":\"Jones\"}]}";
- }
运行结果:
- <p>
- 委托C#方法-返回json字符串
- </p>
- <script type="text/javascript">
- function myfunc(fucPara) {
- return fucPara();
- }
- var res = myfunc(bound.ReturnJsonEmployeeList);
- document.write("委托输出结果:" + res + "<br>");
- var json = JSON.parse(res); //eval("'"+ res+"'");
- document.write("employees 数量:" + json.employees.length + "<br>");
- document.write("json.employees[0].lastName :" + json.employees[0].lastName);
- </script>
- public class SubBoundObject
- {
- public string SimpleProperty { get; set; }
- public SubBoundObject()
- {
- SimpleProperty = "This is a very simple property.";
- }
- public string GetMyType()
- {
- return "My Type is " + GetType();
- }
- public string EchoSimpleProperty()
- {
- return SimpleProperty;
- }
- }
- public SubBoundObject SubObject {
- get;
- set;
- }
- public SubBoundObject GetSubObject() {
- return SubObject;
- }
运行结果:
- <p>
- 返回实体对象
- </p>
- <script type="text/javascript">
- document.write("bound.GetSubObject().SimpleProperty : " + bound.GetSubObject().SimpleProperty);
- </script>
禁用右击菜单需要创建一个类实现接口 IContextMenuHandler,然后把这个类赋值给 ChromiumWebBrowser 的 MenuHandler 即可。这里创建类 MenuHandler:
- internal class MenuHandler : IContextMenuHandler
- {
- public void OnBeforeContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model)
- {
- model.Clear();
- }
- public bool OnContextMenuCommand(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags)
- {
- return false;
- }
- public void OnContextMenuDismissed(IWebBrowser browserControl, IBrowser browser, IFrame frame)
- {
- }
- public bool RunContextMenu(IWebBrowser browserControl, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback)
- {
- return false;
- }
- }
配置到 ChromiumWebBrowser:
- webBrower.MenuHandler = new Class.MenuHandler();
这里只是禁用了菜单,也可以在相关事件里面增加内容,实现自定义右击菜单、不同页面的不同右击菜单.
使用 WebGL 可以实现很炫的页面效果, 以下这些实例都可以直接应用到一个引入了 CefSharp 的 WinFrom 桌面程序上面.
CefSharp 官方文件 readme.txt 中有以下要求:
重要说明:不想看高 (dan) 达(dan)上 (teng) 分析的,请直接看 5.3 依赖列表
因为我这是 nuget 引入的,debug/release 生成的内容很多,直接运行也是成功的,因此我以发布为例,实际和 debug/release 下的调试是一样的。
首先发布好的内容是这样的
直接运行
会有很多报错,因为 vs 的发布过程中忽略很多依赖内容,下面介绍一下怎么一步步定位到缺少的依赖项:
- setup.exe
,注意目录下出现了一个
- xxx已停止工作-点击关闭程序
,打开显示
- debug.log
说明缺少
, 同上边直接拷贝过来
- natives_blob.bin
- locales\en-US.pak 、 cef.pak、cef_100_percent.pak、cef_extensions.pak
两个之后奇迹发生了.... 抓紧把之前粘的全删了...
- CefSharp.BrowserSubprocess.Core.dll CefSharp.BrowserSubprocess.exe
好了不废话了,经过我的九牛二虎之力,发现加入
- [1226/145245:ERROR:gpu_child_thread.cc(260)] Exiting GPU process due to errors during initialization
- [1226/145245:ERROR:browser_gpu_channel_host_factory.cc(133)] Failed to launch GPU process.
就 OK 了
- libEGL.dll、libGLESv2.dll、d3dcompiler_43.dll、d3dcompiler_47.dll
根据今天初步的部署、测试,感觉 CefSharp 可以算是比较成熟的 CEF 的在. net 下的实现了,JavaScript 和 C# 的交互做的简单易用,感觉可以比较容易的将一个 Web 应用的资源经过一定的重新整合打造成为一个桌面程序.
吐槽:一个字大,因为从根本上是集成了一个 chrome 浏览器,所以以上简单的 Demo 的发布程序的 x64、release 版本就达到了 99.5M,360 压缩、7z 格式压缩后 30.6m,正式项目增加了代码、引入了其他的 dll、资源文件等会更大;不知道有没有方法可以做精简
以上均为个人看法,各路大神请指点
- CefSharpDemo20161227 包含packages 157M
- CefSharpDemo20161227 不含packages 131K