﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>学习日记 &#187; cef</title>
	<atom:link href="https://www.softwareace.cn/?feed=rss2&#038;tag=cef" rel="self" type="application/rss+xml" />
	<link>https://www.softwareace.cn</link>
	<description>时刻想着为自己的产品多做一些对他好的事情</description>
	<lastBuildDate>Fri, 20 Mar 2026 06:58:28 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	
	<item>
		<title>基于.net开发chrome核心浏览器</title>
		<link>https://www.softwareace.cn/?p=838</link>
		<comments>https://www.softwareace.cn/?p=838#comments</comments>
		<pubDate>Wed, 25 Jun 2014 06:00:58 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[二次开发]]></category>
		<category><![CDATA[cef]]></category>

		<guid isPermaLink="false">http://www.softwareace.cn/?p=838</guid>
		<description><![CDATA[本篇我们讲解怎么用CefGlue开发一个最简单的浏览器 一： CefGlue是建立在Cef项目之上的， Cef [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>本篇我们讲解怎么用CefGlue开发一个最简单的浏览器</p>
<p><strong>一：</strong></p>
<p>CefGlue是建立在Cef项目之上的，<br />
Cef项目是C/C++的项目；<br />
CefGlue只不过是通过PInvoke来访问Cef项目生成的一些dll<br />
下面我们来看看Cef项目生成的一些dll和资源都是做什么用的<br />
打开这个目录\cef_binary_3.1453.1236_windows_xilium\Release<br />
libcef.dll&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;&gt;Cef的核心类库<br />
icudt.dll&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;&gt;支持unicode的类库<br />
ffmpegsumo.dll&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&gt;支持音频和视频的类库<br />
d3dcompiler_43.dll&#8212;&#8212;&#8212;&#8212;&#8212;&gt;WinXP下支持3D的类库<br />
d3dcompiler_46.dll&#8212;&#8212;&#8212;&#8212;&#8212;&gt;Win7和之后的Win支持3D的类库<br />
libEGL.dll&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&gt;用于支持3D<br />
libGLESv2.dll&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&gt;用于支持3D</p>
<p>打开目录：\cef_binary_3.1453.1236_windows_xilium\Resources<br />
locales&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&gt;此文件夹存放了各种国家的语言资源<br />
cef.pak&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;&gt;为WebKit相关的资源（谷歌浏览器的核心是webkit）<br />
devtools_resources.pak&#8212;&#8212;&#8212;&gt;调试器的相关资源（我们做的项目是可以使用谷歌浏览器的调试器的）</p>
<p><strong>二：</strong></p>
<p>建立一个winform工程，取名加CefDemo<br />
在程序集中创建一个文件夹取名dll<br />
在程序集的属性里设置此程序集的预先生成事件的命令</p>
<div>
<pre class="crayon-plain-tag">xcopy $(ProjectDir)dll $(TargetDir) /e /i /y</pre>
</div>
<p>这个命令的目的是：每次编译的时候把dll文件夹中的文件拷贝的输出目录中</p>
<p>把\cef_binary_3.1453.1236_windows_xilium\Release此目录下的所有文件都拷贝到CefDemo的dll目录中去<br />
把\cef_binary_3.1453.1236_windows_xilium\Resources此目录下的所有文件和文件夹拷贝到dll目录中去<br />
<strong>注意：</strong>locales子目录下的文件大部分都没有用，你可以把所有的文件都删掉，只留下zh-CN.pak文件。<br />
打开Xilium.CefGlue工程，release编译CefGlue程序集，把生成的Xilium.CefGlue.dll也拷贝到CefDemo的dll目录中去<br />
在CefDemo项目中添加Xilium.CefGlue.dll的引用</p>
<p><strong>三：</strong></p>
<p>修改Program.cs的代码：</p>
<div>
<div><a title="复制代码"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></div>
<p></p><pre class="crayon-plain-tag">static void Main()
        {
            CefRuntime.Load();
            var mainArgs = new CefMainArgs(new string[] { });
            var exitCode = CefRuntime.ExecuteProcess(mainArgs, null);
            if (exitCode != -1)
                return;
            var settings = new CefSettings
            {
                SingleProcess = false,
                MultiThreadedMessageLoop = true,
                LogSeverity = CefLogSeverity.Disable,
                Locale = &quot;zh-CN&quot;
            };
            CefRuntime.Initialize(mainArgs, settings, null);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            if (!settings.MultiThreadedMessageLoop)
            {
                Application.Idle += (sender, e) =&amp;gt; { CefRuntime.DoMessageLoopWork(); };
            }
            Application.Run(new CefBrowser());
            CefRuntime.Shutdown();
        }</pre><p></p>
<div><a title="复制代码"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></div>
</div>
<p>我们来一点一点解释这些代码：</p>
<p>CefRuntime.Load();<br />
此行代码用于加载CEF的运行时<br />
————————————————————————<br />
var mainArgs = new CefMainArgs(new string[] { });<br />
此行代码可以收集命令行参数，用于传递给CEF浏览器<br />
————————————————————————<br />
var exitCode = CefRuntime.ExecuteProcess(mainArgs, null);<br />
if (exitCode != -1)<br />
return;<br />
以上代码用于启动第二个进程，至于用第二个进程做什么，我没有深入研究过（可以是浏览器的第二个进程、也可以是一个可执行文件的）<br />
<strong>注意：</strong>CefRuntime.ExecuteProcess方法必须在程序的入口处调用；<br />
——————————————————————————<br />
var settings = new CefSettings<br />
{<br />
SingleProcess = false,<br />
MultiThreadedMessageLoop = true,<br />
LogSeverity = CefLogSeverity.Disable,<br />
Locale = &#8220;zh-CN&#8221;<br />
};<br />
CEF的配置参数，有很多参数，我们这里挑几个解释一下：<br />
SingleProcess = false：此处目的是使用多进程。<br />
<strong>注意：</strong>强烈不建议使用单进程，单进程不稳定，而且Chromium内核不支持<br />
MultiThreadedMessageLoop = true：此处的目的是让浏览器的消息循环在一个单独的线程中执行<br />
<strong>注意：</strong>强烈建议设置成true,要不然你得在你的程序中自己处理消息循环；自己调用CefDoMessageLoopWork()<br />
Locale = &#8220;zh-CN&#8221;：webkit用到的语言资源，如果不设置，默认将为en-US<br />
<strong>注意：</strong>可执行文件所在的目录一定要有locals目录，而且这个目录下要有相应的资源文件<br />
——————————————————————————————<br />
CefRuntime.Initialize(mainArgs, settings, null);<br />
这句代码把创建的配置信息和命令行信息传递个cef的运行时<br />
此函数必须在应用程序的主线程中调用<br />
——————————————————————————————<br />
if (!settings.MultiThreadedMessageLoop)<br />
{<br />
Application.Idle += (sender, e) =&gt; { CefRuntime.DoMessageLoopWork(); };<br />
}<br />
如果你在前面设置的MultiThreadedMessageLoop为false，<br />
那么你可以加入如上代码，自行调用CefRuntime.DoMessageLoopWork();<br />
——————————————————————————————<br />
CefRuntime.Shutdown();<br />
主进程结束时，要释放CEF的资源，并结束浏览器的进程。</p>
<p><strong>四：</strong></p>
<p>在工程中创建一个窗体，<br />
在设计视图中，把窗口调整到合适的大小<br />
（你想让浏览器变成多大，就调整到多大）<br />
然后我们调整一下这个窗体的一些属性</p>
<div>
<pre class="crayon-plain-tag">this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = &quot;CefBrowser&quot;;
            this.Text = &quot;最简单的实现&quot;;</pre>
</div>
<p>在这篇文章提供的例子，还没有实现浏览器随着容器窗体的大小变化而变化<br />
所以：我们在这里禁用了窗口的最大化功能，也禁用了拖动改变窗口大小的功能。</p>
<p><strong>五：</strong></p>
<p>在窗口的构造函数中加入如下代码：</p>
<div>
<pre class="crayon-plain-tag">var cwi = CefWindowInfo.Create();
cwi.SetAsChild(this.Handle, new CefRectangle(0, 0, this.Width, this.Height));
var bc = new BrowserClient();
var bs = new CefBrowserSettings() { };
CefBrowserHost.CreateBrowser(cwi,bc, bs,&quot;http://www.cnblogs.com/liulun&quot;);</pre>
</div>
<p>然后运行程序，你就看到了一个浏览器，如下图：<br />
<img alt="" src="http://images.cnitblog.com/blog/28932/201305/11123818-f6e3ee63473f48b5b9851c32615d781b.png" /><br />
虽然没有滚动条，窗口也不能拖动改变大小<br />
但是当你把鼠标移动到网页上之后，滚动鼠标滚轮，网页还是会跟着滚动的。</p>
<p><strong>六：</strong></p>
<p>下面我们来详细解释一下上面几句代码的意义</p>
<p>CefWindowInfo是CEF浏览器窗口实现的类，其中包含了在windows、linux、MAC下的具体实现<br />
此类中的Create静态方法负责创建这个类的实例，<br />
我在windows下执行这一句，将得到windows下CEF浏览器的实现方式<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
cwi.SetAsChild(this.Handle, new CefRectangle(0, 0, this.Width, this.Height));<br />
此行代码负责把创建的CEF浏览器窗口与我们创建的winform窗口结合起来<br />
this.Handle就是我们创建的winform窗口的句柄<br />
SetAsChild函数使CEF浏览器窗口作为winform窗口的子窗口呈现<br />
CefRectangle标志着CEF浏览器窗口将出现在父窗口中的位置和大小<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
var bc = new BrowserClient();<br />
BrowserClient是我在工程中新建的一个类<br />
这个类没有任何逻辑和属性，只是继承了CefClient类<br />
CefClient类有很多虚方法以供重写，<br />
比如GetDisplayHandler、GetDownloadHandler、GetJSDialogHandler等等<br />
<strong>注意：</strong>此类很重要，我们将在接下来的章节中为这个类添加很多内容<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
var bs = new CefBrowserSettings() { };<br />
之前我们在Program中设置的是CefSettings<br />
那是针对CEF环境的一些全局设置<br />
这里是CefBrowserSettings<br />
这是针对CEF浏览器环境的一些全局设置<br />
可以在这里配置的参数有很多<br />
比如：<br />
DefaultEncoding（用于所有网页内容的编码方式，默认为ISO-8859-1）<br />
UserStyleSheetLocation（用于所有网页的样式，应该按照这样的格式设置这个字段：data:text/css;charset=utf-8;base64,[csscontent]）<br />
RemoteFonts（用于所有网页的字体）<br />
JavaScript（用于所有网页是否可以执行JS脚本）<br />
JavaScriptOpenWindows（用于所有网页是否可以通过JS来打开窗口）<br />
（还有很多类似的设置，读者可以自己去研究）<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
CefBrowserHost.CreateBrowser(cwi,bc, bs,&#8221;http://www.cnblogs.com/liulun&#8221;);<br />
代码执行到这一行即开始创建浏览器子窗口<br />
CreateBrowser前面三个参数不用多说了<br />
最后一个参数就是你想让浏览器访问的页面<br />
<strong>注意：</strong>这个方法是异步执行的（非阻塞的），也就是说你无法知道什么时候窗口被创建出来，（通过其他方式可以注册窗口创建成功的事件，以后再讲。）</p>
<p><strong>源码下载：</strong></p>
<p>http://files.cnblogs.com/liulun/CefDemo.zip</p>
<p>注意：为了下载方便，我已经去掉了dll文件夹中的资源和需要引用的类库</p>
<p><strong>修改记录：</strong><br />
2013-4-22：创建文章，并完成了一部分内容<br />
2013-4-29：添加了文章的一部分内容，碰到问题停滞不前。<br />
2013-5-02：解决掉问题，更新并添加了大部分内容，修改了文章的排版<br />
2013-5-11：增加了最后一部分内容，修改了排版，通读文章，纠正错别字</p>
]]></content:encoded>
			<wfw:commentRss>https://www.softwareace.cn/?feed=rss2&#038;p=838</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>让CEF支持FLASH(非安装插件的形式)</title>
		<link>https://www.softwareace.cn/?p=837</link>
		<comments>https://www.softwareace.cn/?p=837#comments</comments>
		<pubDate>Wed, 25 Jun 2014 05:43:32 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[二次开发]]></category>
		<category><![CDATA[cef]]></category>

		<guid isPermaLink="false">http://www.softwareace.cn/?p=837</guid>
		<description><![CDATA[测试环境: CEF3 + CefGlue 下载FLASH的NPAPI DLL文件 , 在CEF目录下新建文件夹 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>测试环境:</p>
<p>CEF3 + CefGlue</p>
<p>下载FLASH的NPAPI DLL文件 ,</p>
<p>在CEF目录下新建文件夹plugins,然后把DLL文件放进去即可.</p>
<p><img alt="" src="http://images.cnitblog.com/blog/515842/201311/05094417-16236ebc379d4ff3b1967f770e30ac87.png" /></p>
<p>&nbsp;</p>
<p>据说下面是PPAPI的方式,未测试</p>
<p>&nbsp;</p>
<div>启动的时候加个命令行</div>
<div>
<div>&#8220;E:\XiliumCefGlueDemo\Bin\Xilium.CefGlue.Demo.WinForms.exe&#8221; &#8211;ppapi-out-of-process &#8211;register-pepper-plugins=&#8221;E:\XiliumCefGlueDemo\Bin\PepperFlash\pepflashplayer.dll;application/x-shockwave-flash&#8221;</div>
</div>
<div>后边的值要自己改  application/x-ppapi也要改成对应的</div>
<div>如果是在程序中注册 前面的程序路径就不需要，把后面的放在Main函数的Args里  是数组 多个就放多个</div>
]]></content:encoded>
			<wfw:commentRss>https://www.softwareace.cn/?feed=rss2&#038;p=837</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>给Qt内嵌CEF</title>
		<link>https://www.softwareace.cn/?p=828</link>
		<comments>https://www.softwareace.cn/?p=828#comments</comments>
		<pubDate>Wed, 18 Jun 2014 06:09:52 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[cef]]></category>

		<guid isPermaLink="false">http://www.softwareace.cn/?p=828</guid>
		<description><![CDATA[&#160; 目录[-] 给Qt内嵌一个Chrome吧 CEF简述 参考 环境准备 Qt环境 CEF环境 参考 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>&nbsp;</p>
<p>目录[-]</p>
<div id="AnchorContent">
<ul>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h1_1">给Qt内嵌一个Chrome吧</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h2_2">CEF简述</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_3">参考</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h2_4">环境准备</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_5">Qt环境</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_6">CEF环境</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_7">参考</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h2_8">CEF编译</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_9">源码</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h2_10">CEF for Qt</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_11">QMake编译</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_12">cefclient for Qt</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h3_13">参考</a></li>
<li><a href="http://my.oschina.net/vaero/blog/208201#OSC_h2_14">其他链接</a></li>
</ul>
</div>
<div>
<h1>给Qt内嵌一个Chrome吧</h1>
<h2><a href="https://code.google.com/p/chromiumembedded/" rel="nofollow">CEF</a>简述</h2>
<p><a href="https://code.google.com/p/chromiumembedded/" rel="nofollow">CEF</a>(Chromium Embedded Framework)，是一个用于开发Web浏览器控件的开源项目，其基于Google Chromium。</p>
<h3>参考</h3>
<ol>
<li><a href="http://yogurtcat.com/posts/cef/hello-cef.html" rel="nofollow">CEF：给客户端内嵌一个Chrome吧</a></li>
<li><a href="http://blog.csdn.net/milado_nju/article/details/7455373" rel="nofollow">理解WebKit和Chromium: Content API和CEF3</a></li>
<li><a href="http://www.cnblogs.com/haippy/category/488559.html" rel="nofollow">CEF3笔记</a></li>
<li><a href="http://blog.csdn.net/daoxwj/article/category/1389739" rel="nofollow">CEF中文教程</a></li>
</ol>
<h2>环境准备</h2>
<h3>Qt环境</h3>
<ul>
<li>Visual Studio 2010 (not Express edition) (详见<a href="http://bbs.51aspx.com/showtopic-44981.html" rel="nofollow">参考1</a>)</li>
<li><a href="http://download.qt-project.org/official_releases/qt/4.8/4.8.5/qt-win-opensource-4.8.5-vs2010.exe" rel="nofollow">Qt libraries 4.8.5 for Windows (VS 2010, 235 MB)</a></li>
<li><a href="http://download.qt-project.org/official_releases/vsaddin/qt-vs-addin-1.1.11-opensource.exe" rel="nofollow">Visual Studio Add-in 1.1.11 for Qt4</a></li>
</ul>
<p>下载，依次安装，尝试建立个Qt工程，运行ok即可。详见<a href="http://blog.csdn.net/kernlen/article/details/9311357" rel="nofollow">参考2</a>。</p>
<h3>CEF环境</h3>
<ul>
<li><a href="https://www.microsoft.com/en-us/download/details.aspx?id=23691" rel="nofollow">Visual Studio 2010 SP1</a></li>
<li><a href="http://msdn.microsoft.com/en-us/library/windows/desktop/hh852363.aspx" rel="nofollow">Windows 8 SDK</a></li>
<li><a href="http://www.microsoft.com/en-us/download/details.aspx?id=6812" rel="nofollow">Jun10 DirectX SDK</a></li>
</ul>
<p>运行配置，详见<a href="http://www.chromium.org/developers/how-tos/build-instructions-windows" rel="nofollow">参考3</a>。不过，我并没有安装 Jun10 DX SDK 。</p>
<ol>
<li>安装 VS10 SP1 ，是因为先前安装了VS2012，编译cefclient时，遇到了 &#8216;LINK : fatal error LNK1123&#8242; 的问题，详见<a href="http://stackoverflow.com/questions/10888391/error-link-fatal-error-lnk1123-failure-during-conversion-to-coff-file-inval" rel="nofollow">参考4</a>。</li>
<li>安装 Win8 SDK ，&#8217;..\Windows Kits\8.0\Include\winrt\asyncinfo.h&#8217; 66行的 class 需要注释掉，<a href="http://www.chromium.org/developers/how-tos/build-instructions-windows" rel="nofollow">参考3</a>内有详细描述。（不安装，应该也能编译发布版的cef）</li>
</ol>
<h3>参考</h3>
<ol>
<li><a href="http://bbs.51aspx.com/showtopic-44981.html" rel="nofollow">Visual Studio各版本下载合集</a></li>
<li><a href="http://blog.csdn.net/kernlen/article/details/9311357" rel="nofollow">QT4.8.5+qt-vs-addin-1.1.11+VS2010安装配置和QT工程的新建和加载</a></li>
<li><a href="http://www.chromium.org/developers/how-tos/build-instructions-windows" rel="nofollow">Build Instructions (Windows)</a></li>
<li><a href="http://stackoverflow.com/questions/10888391/error-link-fatal-error-lnk1123-failure-during-conversion-to-coff-file-inval" rel="nofollow">LINK : fatal error LNK1123</a></li>
</ol>
<h2>CEF编译</h2>
<h3>源码</h3>
<ul>
<li><a href="http://chromiumembedded.googlecode.com/svn/trunk/cef3" rel="nofollow">cef3主分支源码</a></li>
<li><a href="http://www.magpcss.net/cef_downloads/index.php?file=cef_binary_3.1547.1412_windows32.7z" rel="nofollow">cef_binary_3.1547.1412_windows32.7z</a></li>
</ul>
<p>cef3主分支源码，可以用<a href="http://tortoisesvn.net/downloads.html" rel="nofollow">TortoiseSVN</a>来获取。不过，我用的是后一个发布版本。更多可见<a href="http://www.magpcss.net/cef_downloads/" rel="nofollow">CEF Downloads</a>。</p>
<p>解压cef_xxx.7z，打开cefclient2010.sln，F5编译运行。</p>
<h2>CEF for Qt</h2>
<h3>QMake编译</h3>
<p>qmake来编译cef代码。这里新建Qt工程，再将cef代码移过来，进行工程配置。基本步骤如下：</p>
<ol>
<li>新建Qt工程cefclient，Solution为&#8217;qcef&#8217;。</li>
<li>右键Solution，追加libcef_dll的Qt static lib工程。</li>
<li>右键Solution &gt; Properties &gt; Common &gt; Dependencies，cefclient depends on libcef_dll。</li>
<li>配置工程的各输出目录，可修改配置有：
<ul>
<li>Project &gt; Properties &gt; Configuration .. &gt; General: Output Directory, Intermediate Directory</li>
<li>Qt &gt; Qt Project Settings &gt; Properties: MocDirectory, RccDirectory, UicDirectory</li>
<li>VS C++开发时ipch、sdf的输出目录，可如下修改（严重洁癖症患者）:
<ul>
<li>Tools &gt; Options &gt; Text Editor &gt; C/C++ &gt; Advanced &gt; Fallback Location: Ture, True, Output Directory</li>
</ul>
</li>
</ul>
</li>
<li>复制cef的 Debug, Release, include, Resources 到Solution目录下。
<ul>
<li>Debug, Release为发布版cef给我们编译好的lib，include为头文件，Resources为其资源。</li>
</ul>
</li>
<li>libcef_dll的代码移过来，Show All Files &gt; Refresh &gt; Delete多余的 &gt; Include所有代码。</li>
<li>libcef_dll工程属性配置，之后编译。右键Properties &gt; Configuration ..：
<ul>
<li>General &gt; Character Set: Use Unicode Character Set</li>
<li>C/C++ &gt; General &gt; Additional Include ..: + &#8216;..&#8217;(上级目录), 或$(SolutionDir)</li>
<li>C/C++ &gt; Preprocessor &gt; Preprocessor Definitions: + &#8216;NOMINMAX, USING_CEF_SHARED&#8217;</li>
</ul>
</li>
<li>qcefclient的代码移过来，同libcef_dll一样，之后配置编译：
<ul>
<li>General &gt; Character Set: Use Unicode Character Set</li>
<li>C/C++ &gt; General &gt; Additional Include ..: + &#8216;..&#8217;(上级目录), 或$(SolutionDir)</li>
<li>C/C++ &gt; Preprocessor &gt; Preprocessor Definitions: + &#8216;NOMINMAX&#8217;</li>
<li>Linker &gt; Input &gt; Additional Dependencies:
<ul>
<li>.\..\$(Configuration)\libcef.lib : cef的lib</li>
<li>.\..\out\$(Configuration)\lib\libcef_dll.lib : libcef_dll工程的lib</li>
<li>opengl32.lib : opengl的lib，或Qt Project Settings &gt; Qt Modules勾选OpenGL library</li>
</ul>
</li>
</ul>
</li>
<li>输出目录缺少cef运行的必要dll等，需要把先前复制的cef的Debug或Release和Resources内的文件复制到输出目录。
<ul>
<li>可以配置预执行命令，右键Properties &gt; Configuration .. &gt; Build Events &gt; Pre-Build Event &gt; Command Line:
<ul>
<li>xcopy $(SolutionDir)$(Configuration) $(SolutionDir)out\$(Configuration) /e /d</li>
<li>xcopy $(SolutionDir)Resources $(SolutionDir)out\$(Configuration) /e /d</li>
<li>有不需要复制的文件，可将其名称放到一个文件里。然后在xcopy命令最后加exclude参数，如&#8217;/exclude:$(SolutionDir)exclude.list&#8217;。更多<a href="http://baike.baidu.com/view/893375.htm" rel="nofollow">xcopy参数</a>。</li>
</ul>
</li>
</ul>
</li>
</ol>
<h3>cefclient for Qt</h3>
<p>简单浏览遍cefclient的代码，如下：</p>
<ul>
<li>binding_test.cpp</li>
<li>binding_test.h &gt; 绑定测试：获取进程消息及其回复，与js通信。对应binding.html</li>
<li>cefclient.cpp</li>
<li>cefclient.h &gt; 全局方法：cef全局方法，测试方法实现等</li>
<li>cefclient_osr_widget_win.cpp</li>
<li>cefclient_osr_widget_win.h &gt; OpenGL渲染窗口组件</li>
<li>cefclient_win.cpp &gt; 应用程序入口：初始化cef，建立windows窗口等</li>
<li>client_app.cpp</li>
<li>client_app.h &gt; CefApp回调处理类：其被传递给了CefExecuteProcess(), CefInitialize()
<ul>
<li>设计了浏览器委托和渲染器委托流程。后一测试有dom_test，performance_test。</li>
<li>另有自定义协议注册，测试为scheme_test。</li>
<li>这里也注册了js消息调用的扩展，app对象及其方法。</li>
</ul>
</li>
<li>client_app_delegates.cpp</li>
<li>client_handler.cpp</li>
<li>client_handler.h &gt; CefClient回调处理类：其被传递给了CefBrowserHost::CreateBrowser()
<ul>
<li>设计了进程消息委托流程。测试包括binding_test, dialog_test, window_test。</li>
</ul>
</li>
<li>client_handler_win.cpp</li>
<li>client_renderer.cpp</li>
<li>client_renderer.h &gt; 客户端渲染委托：处理节点焦点事件</li>
<li>client_switches.cpp</li>
<li>client_switches.h &gt; 用到的命令行参数：<a href="http://peter.sh/experiments/chromium-command-line-switches/" rel="nofollow">More Switches</a></li>
<li>dialog_test.cpp</li>
<li>dialog_test.h &gt; 对话框测试：对应dialogs.html</li>
<li>dom_test.cpp</li>
<li>dom_test.h &gt; dom元素选择测试：对应domaccess.html</li>
<li>osrenderer.cpp</li>
<li>osrenderer.h &gt; OpenGL渲染器</li>
<li>performance_test.cpp</li>
<li>performance_test.h &gt; V8性能测试：对应performance.html, performance2.html</li>
<li>performance_test_setup.h</li>
<li>performance_test_tests.cpp</li>
<li>resource.h &gt; 资源头文件</li>
<li>resource_util.h &gt; 资源工具：由名称获取字符串资源、由名称获取资源字节流</li>
<li>resource_util_win.cpp</li>
<li>scheme_test.cpp</li>
<li>scheme_test.h &gt; 自定义协议测试：client://</li>
<li>string_util.cpp</li>
<li>string_util.h &gt; 字符串工具：请求信息转为字符串、字符串替换</li>
<li>util.h &gt; 一些断言宏：检验Cef当前线程类型</li>
<li>window_test.cpp</li>
<li>window_test.h &gt; 窗口测试：对应window.html</li>
<li>window_test_win.cpp</li>
</ul>
<p>然后，开始动手术，改造为Qt窗口：</p>
<p><strong>直接参见改造后的工程<a href="https://github.com/joinAero/qtcefclient" rel="nofollow">qtcefclient</a>。</strong></p>
<h3>参考</h3>
<ol>
<li><a href="http://stackoverflow.com/questions/14170770/unresolved-external-symbol-public-virtual-struct-qmetaobject-const-thiscal" rel="nofollow">LNK2001: unresolved external symbol … QMetaObject …</a></li>
<li><a href="http://blog.erikd.org/2013/01/14/chromium-embedded-framework-3-bare-bones/" rel="nofollow">CEF3 &#8211; Bare Bones</a></li>
<li><a href="http://www.oschina.net/news/44169/introducing-the-qt-webengine" rel="nofollow">Qt决定将Web渲染引擎从WebKit改为Chromium</a></li>
</ol>
<h2>其他链接</h2>
<ul>
<li><a href="http://liulanmi.com/tools" rel="nofollow">浏览器测试工具</a></li>
<li><a href="http://tcspecial.iteye.com/blog/1753104" rel="nofollow">QT下新建windows窗体</a></li>
<li><a href="http://my.eoe.cn/shifo/archive/901.html" rel="nofollow">Windows8开发书籍汇总</a></li>
</ul>
<hr />
<p>部分Web引擎框架相关链接</p>
<ul>
<li><a href="http://www.webkit.org/" rel="nofollow">WebKit</a></li>
<li><a href="http://www.chromium.org/Home" rel="nofollow">Chromium</a></li>
</ul>
<p><strong>C++</strong></p>
<ul>
<li><a href="https://code.google.com/p/chromiumembedded/" rel="nofollow">CEF</a></li>
<li><a href="http://www.awesomium.com/" rel="nofollow">Awesomium</a></li>
</ul>
<p><strong>Qt</strong></p>
<ul>
<li><a href="http://qt-project.org/wiki/QtWebEngine" rel="nofollow">QtWebEngine</a></li>
<li><a href="https://launchpad.net/oxide" rel="nofollow">Oxide Webview</a></li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>https://www.softwareace.cn/?feed=rss2&#038;p=828</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CEF：给客户端内嵌一个Chrome</title>
		<link>https://www.softwareace.cn/?p=826</link>
		<comments>https://www.softwareace.cn/?p=826#comments</comments>
		<pubDate>Wed, 18 Jun 2014 01:04:54 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[cef]]></category>

		<guid isPermaLink="false">http://www.softwareace.cn/?p=826</guid>
		<description><![CDATA[CEF是什么 CEF是Chromium Embedded Framework的缩写，是个基于Google Ch [&#8230;]]]></description>
				<content:encoded><![CDATA[<h3>CEF是什么</h3>
<p>CEF是<a href="http://code.google.com/p/chromiumembedded/" target="_blank">Chromium Embedded Framework</a>的缩写，是个基于Google Chromium项目的开源Web browser控件，支持Windows, Linux, Max平台。除了提供C/C++接口外，也有其他语言的移植版。</p>
<p>因为基于Chromium，所以CEF支持Webkit &amp; Chrome中实现的HTML5的特性，并且在性能上面，也比较接近Chrome。</p>
<p>CEF还提供的如下特性：自定义插件、自定义协议、自定义JavaScript对象和扩展；可控制的resource loading, navigation, context menus等等。</p>
<h3>谁在用CEF</h3>
<p>让我们通过一些实战中的例子，来说明大家都使用CEF做了什么：</p>
<ul>
<li>
<h5>各种浏览器</h5>
<p>早期的双核浏览器(IE + Webkit)，有些使用了CEF来作为Webkit内核浏览器控件。</p>
<p>不过对于浏览器来说，直接在Chrome上面扩展，其实才是王道，大家现在都这么做了（各种极速浏览器）。</li>
<li>
<h5>Evernote Client (on Windows)</h5>
<p>Evernote允许用户将网页粘贴到笔记中，还提供了插件用来将网页保存为笔记。</p>
<p>那肯定是需要在Client上面可以正确的渲染页面咯，这个任务就交给了CEF。</li>
<li>
<h5>GitHub Client (on Windows)</h5>
<p>GitHub也打包了libcef.dll，从表现上面看，用来展示项目的ReadMe页面的，肯定是CEF，其他地方的UI，可能部分也是用页面来实现的。</li>
<li>
<h5>QQ</h5>
<p>QQ很早之前就通过内嵌IE来实现一些功能和界面。从去年开始，QQ引入了CEF，对一些之前用IE的地方进行了替换，这样就可以使用一些基于Webkit的新特性，同时也获得了速度、稳定性、兼容性方面的优势。</li>
<li>
<h5>Adobe Edge Animate &amp; Adobe Edge Reflow</h5>
<p>Adobe推出了一整套制作现代网页(或者说HTML5?)的工具，取名<a href="http://html.adobe.com/edge/" target="_blank">Edge</a>。</p>
<ul>
<li>Adobe Edge Animate，做动画用的，可以通过编辑时间线，创建原件(Edge Animate里面叫做symbol)，来实现复杂的动画。</li>
<li>Edge Reflow则是Design the responsive web. 有人翻译为响应式，其实就是自适应了。</li>
</ul>
<p>上面两款软件，其基本面向的是Webkit内核的浏览器，那么内嵌一个Webkit内核，来提供所见即所得的预览、编辑界面就是必须的了。他们都使用了CEF。（后面会介绍CEF和纯Webkit的差别）</li>
<li>
<h5>Q+</h5>
<p>Q+在Web App的概念下，为Web页面提供了一个运行环境(简单来说就是：Client的一个框和一些可用的API)，支持IE和Webkit内核。</p>
<p>对Web开发同学来说，我们引入的Webkit内核（实际上是CEF），无需考虑IE的版本兼容问题，既提高了开发效率，又可以利用一些新的HTML5特性。当时Q+的应用市场、消息中心、壁纸、音乐Widget等应用都是基于Webkit内核开发的。</p>
<p>Q+项目可以说对CEF进行了比较多的尝试，比如：</p>
<ul>
<li>开发的音乐Widget，就使用了HTML5的audio标签；</li>
<li>一些应用使用了HTML5的离线功能（就是配个manifest文件那个），当然其中也遇到些曲折，收获了不少经验。</li>
<li>打包的Webkit调试工具（Dev Tools）。</li>
<li>自定义协议：比如对qplus://协议的访问，可以重定向到某个特殊文件夹之类的功能。</li>
<li>Off Screen Rendering（OSR，离屏渲染）：通过离屏渲染 + Windows的Layered Window，就制作了不规则的网页窗口（网页不透明区域是什么形状，窗口就是什么形状）</li>
</ul>
</li>
</ul>
<h3>为什么要给客户端内嵌CEF？</h3>
<p>举了那么多例子之后，这个问题说起来就容易多了：</p>
<ul>
<li>
<h5>用来展示Web页面，使用各种Web Service；</h5>
</li>
<li>
<h5>用Web页面来做UI；</h5>
</li>
<li>
<h5>使用HTML5的特性，比如audio、canvas等，包括CSS3特性等。</h5>
</li>
<li>
<h5>Off Screen Rendering（OSR，离屏渲染）：</h5>
<p>所谓的OSR，就是不创建真窗口，将整个页面渲染到一张位图上面。当然不只是渲染，还有一系列的API来处理鼠标、键盘事件，处理输入法事件等。</p>
<p>这个特性在不能使用真窗口的时候特别有用，比如Layered Window上面，或者是游戏中渲染到Texture上。</p>
<p>利用OSR特性，可以做出一些有趣的效果，比如：</p>
<p>AlloyTeam做出了<a href="http://yogurtcat.com/posts/cef/webtop.alloyteam.com" target="_blank">Webtop</a>，里面用OSR做了纯网页实现的浏览器、播放器等。</p>
<p>有一个Awesomium项目，也是支持OSR，已经有游戏项目用Awesomium来在游戏中渲染网页了。 （看Awesomium的输出文件，应该和CEF的实现方式差不多，都是对Chromium的封装，Awesomium能做的CEF应该也可以做）</p>
<p>我业余时间做了一个<a href="https://github.com/zhaojunmeng/BIG" target="_blank">demo</a>，用CEF将网页渲染到了OpenGL的Texture上面，也算是将CEF应用在游戏中的一小步尝试，如图：</p>
<p><img title="in-game browser demo" alt="in-game browser demo" src="http://yogurtcat.com/assets/image/cef/cef-in-game-demo.jpg" /></li>
</ul>
<h3>Why CEF?（CEF vs 其他可选方案）</h3>
<h4>IE</h4>
<p>IE作为内嵌的浏览器控件已经有很久的历史了，准确的说是现在我们有了很多可以替代IE的方案。</p>
<p>CEF vs IE：</p>
<ul>
<li>
<h5>兼容性：</h5>
<p>IE：内核随着操作系统不同，版本从6到10，Web开发对这些版本的兼容工作量不可小视。</p>
<p>CEF：使用的是Webkit内核，从特性上看，一个CEF版本，可以对应一个Chrome的版本号，这样Web开发就有了明确的特性集合，免去了考虑兼容性的工作量。</li>
<li>
<h5>HTML5标准 &amp; 新特性：</h5>
<p>IE：当然旧版本的IE也不支持最新的HTML特性和标准。</p>
<p>CEF：毫无疑问，在对新特性的支持上Webkit和Chrome都是走在前沿的。</li>
<li>
<h5>开源 &amp; 跨平台：</h5>
<p>IE：不开源，限Windows平台</p>
<p>CEF：开源，使用的Webkit, Chromium都是开源的，开源就意味着更多可定制的可能；且跨Windows, Mac, Linux3个平台。</li>
<li>
<h5>离屏渲染（OSR）：</h5>
<p>IE：可以通过一些hack的方法来实现离屏渲染，但是工作量不小，而且不是官方支持的。</p>
<p>CEF：有专门的离屏渲染模式和对应的API。</li>
<li>
<h5>普及率：</h5>
<p>IE：所有Windows用户都有IE，这是IE的优势（不过有些用户的IE设置不正缺，会导致无法使用，比如jscript.dll未注册，导致无法使用JavaScript）</p>
<p>CEF：要自己更安装包打包</li>
</ul>
<h4>Webkit</h4>
<p>为什么要特意将CEF和Webkit做对比呢？</p>
<p>最近看了一篇很好的文章，讲了Webkit到底是什么，不是什么，以及为什么要有那么多的Webkit port： <a href="http://www.infoq.com/cn/articles/webkit-for-developers" target="_blank">《开发者需要了解的WebKit》</a></p>
<p>这里大概总结一下：</p>
<p>Webkit是网页的解析和排布引擎，是所有基于Webkit的浏览器共享的。默认的Webkit port是Safari，就是下载下来Webkit源码编译的版本。 除此之外还有其他的Webkit port，包括Chromium, QtWebkit等，在2D绘图、GPU加速、JavaScript引擎、audio/video解码等，都有不同的实现。</p>
<ul>
<li>
<h5>CEF vs webkit（其实可以说是Chromium vs Webkit）</h5>
<p>V8引擎，skia的2D渲染，Chromium的GPU加速的实现，等等，借助Chromium的优秀实现，使CEF也成为了一个优秀的Webkit port。</li>
</ul>
<h3>CEF缺点：</h3>
<p>做人要厚道，CEF也有自己的缺点和局限，也不能只提优点，这里我把CEF的缺点、劣势介绍一下：</p>
<ul>
<li>
<h5>体积：</h5>
<p>最新版的CEF，所有DLL体积加起来，应该接近40M了，压缩之后估计也要10M+。 如果你的项目本身安装包体积就不大，并且也无法接收这体积，那CEF不适合你。</p>
<p>当然对于现在按G来计算的游戏的话，这个体积应该还是可以接受的。</p>
<p>普通的Client项目，就看项目本身需要使用CEF实现的特性，是否值得让产品的安装包增大这么多。 当然这里也有一些实现上的妥协，比如做安装后下载（个人认为这个意义不大，毕竟安装包用户还可以选择用下载软件来加速）</li>
<li>
<h5>缓存：</h5>
<p>Chrome的缓存设计成只能有一个进程读写，CEF自然也是如此。</p>
<p>对于需要多开的Client，目前只能每个进程实例指定一个不同的缓存文件夹。但是这无疑增加了硬盘占用，也使某些本来被缓存的文件被下载了多次（比如A进程缓存了jQuery.js，B进程由于缓存不同目录，还得去请求、缓存一次jQueyr.js）</li>
<li>
<h5>OSR：</h5>
<p>OSR目前不像真窗口模式那样，可以使用GPU加速，OSR目前还只能使用软件渲染，也就是说一些CSS 3D的效果无法支持。</p>
<p>不过OSR的特性还在不停完善中，个人认为还是值得期待。</li>
</ul>
<h3>后续要分享的内容</h3>
<p>写了这么多，算是一个CEF的简介吧，后续要写点儿干货，即如何使用CEF，包括：</p>
<p>CEF代码获取，编译，嵌入，处理页面和Client的API调用，OSR离屏渲染，缓存，自定义协议，CEF1 &amp; CEF3等。</p>
<p>http://yogurtcat.com/posts/cef/hello-cef.html</p>
]]></content:encoded>
			<wfw:commentRss>https://www.softwareace.cn/?feed=rss2&#038;p=826</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CEF1和CEF3两个版本的区别</title>
		<link>https://www.softwareace.cn/?p=825</link>
		<comments>https://www.softwareace.cn/?p=825#comments</comments>
		<pubDate>Wed, 18 Jun 2014 01:02:55 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[二次开发]]></category>
		<category><![CDATA[cef]]></category>

		<guid isPermaLink="false">http://www.softwareace.cn/?p=825</guid>
		<description><![CDATA[早在content API出现之前，CEF便已出现，其目的是提供嵌入式的框架，可以让渲染网页的功能方便地嵌入到 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>早在content API出现之前，CEF便已出现，其目的是提供嵌入式的框架，可以让渲染网页的功能方便地嵌入到应用程序之中。CEF依赖于chromium浏览器，所以chromium对HTML5的支持和性能上的优势，都得以继续在CEF中体现出来。但是，根据实际测试的结果来看，情况可能并非如此。首先，其对GPU硬件加速的支持不是很好，这时因为它会把GPU内存读回到CPU内存，速度非常慢；再次，因为基于chromium的内部结构，而它们经常变化，所以CEF经常需要发生变化，这对维护来说是件很头痛的事。<br />
得益于content API的出现，CEF的作者也基于它开发了CEF3。CEF3在保持其提供的接口基本不变的情况下，借助content API的能力，其对HTML5和GPU硬件加速提供了较好的支持。它的核心变为调用content API的接口和实现content API的回调接口，来组织和包装成CEF3自己的接口以被其他开发者所使用。其好处是，CEF3的接口相对比较简单，使用起来方便，同时不需要实现很多content API的回调接口，但是缺点就是，如果需要使用content API的很多功能，CEF3的接口可能做不到，或者说只能通过直接调用content API接口来完成。<br />
下面简单介绍一下CEF3的接口。<br />
CefClient：回调管理类，包含5个接口用于创建其它的回调类的对象<br />
CefLifeSpanHandler: 回调类，用于控制popup对话框的创建和关闭等操作<br />
CefLoadHandler: 回调类，可以用来监听frame的加载开始，完成，错误等信息<br />
CefRequestHandler: 回调类，用于监听资源加载，重定向等信息<br />
CefDisplayHandler: 回调类，用于监听页面加载状态，地址变化，标题等得信息<br />
CefGeolocationHandler: 回调类，用于CEF3向嵌入者申请geolocation的权限<br />
CefApp: 与进程，命令行参数，代理，资源管理相关的回调类，用于让CEF3的调用者们定制自己的逻辑<br />
CefBrowser: renderer进程中执行浏览相关的类，例如前进，后退等<br />
CefBrowserHost: browser进程中的执行浏览相关的类，其会把请求发送给CefBrowser<br />
CefFrame: 表示的是页面中的一个Frame，可以加载特定url，在该运行环境下执行JavaScript代码等得。<br />
V8：CEF3提供支持V8extension的接口，但是这有两个限制，第一，v8 extension仅在Renderer进程使用；第二，仅在沙箱模型关闭时使用。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.softwareace.cn/?feed=rss2&#038;p=825</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
