<?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>CEF &#8211; 编程技术记录</title>
	<atom:link href="https://blog.z6z8.cn/category/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/cef/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.z6z8.cn</link>
	<description>世界你好!</description>
	<lastBuildDate>Wed, 23 Mar 2022 09:25:18 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
	<item>
		<title>【CEF3学习】– 在同一窗口打开链接</title>
		<link>https://blog.z6z8.cn/2022/03/23/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e5%9c%a8%e5%90%8c%e4%b8%80%e7%aa%97%e5%8f%a3%e6%89%93%e5%bc%80%e9%93%be%e6%8e%a5/</link>
		
		<dc:creator><![CDATA[holdsky]]></dc:creator>
		<pubDate>Wed, 23 Mar 2022 09:25:18 +0000</pubDate>
				<category><![CDATA[CEF]]></category>
		<category><![CDATA[学习笔记]]></category>
		<guid isPermaLink="false">http://blog.z6z8.cn/?p=1213</guid>

					<description><![CDATA[本次着手实现将 target=&#34;_blank&#34;的行为修改为 target=&#34;_s [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>本次着手实现将 <code>target=&quot;_blank</code>&quot;的行为修改为 <code>target=&quot;_self&quot;</code>。</p>
<p>CEF3提供了UI窗口生命周期接口<code>CefLifeSpanHandler</code>，借助这个接口来监听新窗口创建事件，并在创建前取消窗口创建，使用已有窗口来加载新链接。</p>
<pre><code class="language-c++">class CefLifeSpanHandler : public virtual CefBaseRefCounted {
 public:
  ///由UI线程调用，调用时机是新浏览窗口创建前。
  // frame 弹出新窗口链接的源frame（即从哪个frame里的链接弹出新窗口）
  // target_url 目的链接
  // target_frame_name 目的frame名字
  // 返回true，则表示要取消窗口创建
  virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
                             const CefString& target_url,
                             const CefString& target_frame_name,
                             WindowOpenDisposition target_disposition,
                             bool user_gesture,
                             const CefPopupFeatures& popupFeatures,
                             CefWindowInfo& windowInfo,
                             CefRefPtr<CefClient>& client,
                             CefBrowserSettings& settings,
                             CefRefPtr<CefDictionaryValue>& extra_info,
                             bool* no_javascript_access) 
{
    frame->LoadURL(target_url); //在当前frame中加载链接
    return true; //返回true，取消窗口创建
}
</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【CEF3学习】&#8211; 文件下载管理</title>
		<link>https://blog.z6z8.cn/2022/03/23/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e6%96%87%e4%bb%b6%e4%b8%8b%e8%bd%bd%e7%ae%a1%e7%90%86/</link>
		
		<dc:creator><![CDATA[holdsky]]></dc:creator>
		<pubDate>Wed, 23 Mar 2022 07:04:02 +0000</pubDate>
				<category><![CDATA[CEF]]></category>
		<category><![CDATA[学习笔记]]></category>
		<guid isPermaLink="false">http://blog.z6z8.cn/?p=1205</guid>

					<description><![CDATA[CEF3关于文件下载的开放接口是CefDownloadHandler，这个类的公开函数也挺简单的，就两个：一个 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>CEF3关于文件下载的开放接口是<code>CefDownloadHandler</code>，这个类的公开函数也挺简单的，就两个：一个是下载前<code>OnBeforeDownload</code>，一个是下载状态更新<code>OnDownloadUpdated</code></p>
<pre><code class="language-c++">class CefDownloadHandler : public virtual CefBaseRefCounted {
 public:
  /// 文件下载前调用
  // suggested_name  （建议的）文件保存名
  // callback  回调，用来通知下载动作继续进行。默认情况下，如果不主动调用这个回调，则会取消下载动作。
  virtual void OnBeforeDownload(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefDownloadItem> download_item,
      const CefString& suggested_name,
      CefRefPtr<CefBeforeDownloadCallback> callback) = 0;

  /// 用来通知下载状态信息，包括下载进度、总大小、已完成大小、是否完成等；这个方法可能会被调用多次，以用来持续更新下载状态
 // download_item  下载项，下载的状态信息保存在这里。
 // callback  回调，用来取消/暂停/恢复/下载。默认情况下，如果不主动调用这个回调，则会继续下载。
  virtual void OnDownloadUpdated(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefDownloadItem> download_item,
                                 CefRefPtr<CefDownloadItemCallback> callback) {}
};</code></pre>
<p>需要注意的是，上面两个方法都有一个<code>download_item</code>参数，这个参数是不能在上面两个方法的作用域外使用的。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【CEF3学习】&#8211; 修改User-Agent</title>
		<link>https://blog.z6z8.cn/2022/03/09/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e4%bf%ae%e6%94%b9user-agent/</link>
		
		<dc:creator><![CDATA[holdsky]]></dc:creator>
		<pubDate>Wed, 09 Mar 2022 02:34:37 +0000</pubDate>
				<category><![CDATA[CEF]]></category>
		<category><![CDATA[学习笔记]]></category>
		<guid isPermaLink="false">http://blog.z6z8.cn/?p=1195</guid>

					<description><![CDATA[本文要实现的是在右键菜单中添加一个修改User-Agent功能 定义一个变量，用来控制是使用默认UA还是And [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>本文要实现的是在<a href="https://139.155.43.7/2022/03/07/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e6%b7%bb%e5%8a%a0%e5%8f%b3%e9%94%ae%e8%8f%9c%e5%8d%95">右键菜单</a>中添加一个修改User-Agent功能<br />
<img decoding="async" src="/wp-content/uploads/2022/03/1-1.png" alt="" /></p>
<p>定义一个变量，用来控制是使用默认UA还是Android UA</p>
<pre><code class="language-cpp">static bool s_UerAgentAndroid = false;</code></pre>
<p>添加<a href="https://139.155.43.7/2022/03/07/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e6%b7%bb%e5%8a%a0%e5%8f%b3%e9%94%ae%e8%8f%9c%e5%8d%95">右键菜单</a></p>
<pre><code class="language-cpp">// 添加菜单枚举
enum client_menu_ids {
    CLIENT_ID_SHOW_DEVTOOLS = MENU_ID_USER_FIRST,
  ...
  ....
    CLIENT_ID_UserAnget,
};

// 修改菜单项和菜单事件处理
void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
                                        CefRefPtr<CefFrame> frame,
                                        CefRefPtr<CefContextMenuParams> params,
                                        CefRefPtr<CefMenuModel> model) {
    ......
    ......
    //添加菜单项
    model->AddItem(CLIENT_ID_UserAnget, s_UerAgentAndroid ? "默认UA":"Android UA");
  if (delegate_)
    delegate_->OnBeforeContextMenu(model);
}

bool ClientHandler::OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
                                         CefRefPtr<CefFrame> frame,
                                         CefRefPtr<CefContextMenuParams> params,
                                         int command_id,
                                         EventFlags event_flags) {
  CEF_REQUIRE_UI_THREAD();

  switch (command_id) {
     ......
     ......
     //菜单事件处理
    case CLIENT_ID_UserAnget:
          s_UerAgentAndroid = !s_UerAgentAndroid;
          browser->Reload(); // 修改UA后重新加载网页
          return true;
    default:  // Allow default handling, if any.
      return ExecuteTestMenu(command_id);
  }
}</code></pre>
<p>下面就是对每一个请求修改HTTP报文的User-Agent。CEF3会将网页所有资源请求事件通知给<code>CefRequestHandler</code>或其子类处理，其<code>OnBeforeResourceLoad</code>是在http请求发出前的处理点，修改相应内容，代码如下</p>
<pre><code class="language-cpp">cef_return_value_t ClientHandler::OnBeforeResourceLoad(
    CefRefPtr<CefBrowser> browser,
    CefRefPtr<CefFrame> frame,
    CefRefPtr<CefRequest> request,
    CefRefPtr<CefCallback> callback) {
    ......
    ......
    if (s_UerAgentAndroid) {
       //设置UA字段
        request->SetHeaderByName("User-Agent", "Mozilla/5.0 (Android5.1.1)", true);
    }
  return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
                                                 callback);
}</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【CEF3学习】&#8211; 添加右键菜单</title>
		<link>https://blog.z6z8.cn/2022/03/07/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e6%b7%bb%e5%8a%a0%e5%8f%b3%e9%94%ae%e8%8f%9c%e5%8d%95/</link>
		
		<dc:creator><![CDATA[holdsky]]></dc:creator>
		<pubDate>Mon, 07 Mar 2022 09:59:46 +0000</pubDate>
				<category><![CDATA[CEF]]></category>
		<category><![CDATA[学习笔记]]></category>
		<guid isPermaLink="false">http://blog.z6z8.cn/?p=1182</guid>

					<description><![CDATA[cefclient这个项目启动后，默认情况下会有下图所示的右键菜单 我们要做的就是仿照这个菜单，添加新的菜单项 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>cefclient这个项目启动后，默认情况下会有下图所示的右键菜单<br />
<img decoding="async" src="/wp-content/uploads/2022/03/6.png" alt="" /></p>
<p>我们要做的就是仿照这个菜单，添加新的菜单项。<br />
根据关键字搜索，可以找到client_handler.cpp文件，有两函数<code>OnBeforeContextMenu</code>、<code>OnContextMenuCommand</code>，用来处理菜单项。修改这两个函数，增加新的菜单项，例如重新加载当前页面。</p>
<pre><code class="language-cpp">///
enum client_menu_ids {
  CLIENT_ID_SHOW_DEVTOOLS = MENU_ID_USER_FIRST,
  ....
  CLIENT_ID_TESTMENU_RADIOITEM3,
  CLIENT_ID_RELOAD_PAGE /// 添加一个菜单项枚举
};

void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
                                        CefRefPtr<CefFrame> frame,
                                        CefRefPtr<CefContextMenuParams> params,
                                        CefRefPtr<CefMenuModel> model) {
        ///在菜单显示前，处理菜单项
        ....
          model->AddItem(CLIENT_ID_RELOAD_PAGE, "重新加载页面");
       ....

}

bool ClientHandler::OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
                                         CefRefPtr<CefFrame> frame,
                                         CefRefPtr<CefContextMenuParams> params,
                                         int command_id,
                                         EventFlags event_flags){
  ///对应菜单项的响应处理
    switch (command_id) {
    case CLIENT_ID_RELOAD_PAGE:
       browser->Reload();
      return true;
     case CLIENT_ID_SHOW_DEVTOOLS:
     .....
     ...
     }
}</code></pre>
<p><img decoding="async" src="/wp-content/uploads/2022/03/6-1.png" alt="" /></p>
<p>至此，添加右键菜单的需求实现了。<br />
再回过来看看<code>ClientHandler</code>，看它的定义</p>
<pre><code class="language-cpp">class ClientHandler : public CefClient,
                      public CefContextMenuHandler,
                      public CefDisplayHandler,
                      public CefDownloadHandler,
                      public CefDragHandler,
                      public CefFocusHandler,
                      public CefKeyboardHandler,
                      public CefLifeSpanHandler,
                      public CefLoadHandler,
                      public CefRequestHandler,
                      public CefResourceRequestHandler </code></pre>
<p><code>ClientHandler</code>采用多继承方式，把上下文菜单、显示状态、下载、拖拽、焦点、键盘等浏览器事件集中起来处理，如果我们要修改相关需求，改变ClientHandler的对应实现就可以了。</p>
<p>那么ClientHandler是在什么时候注册到事件循环中的？通过断点查看调用栈，大致的过程如下：</p>
<p>CefBrowserHost::CreateBrowser()  创建浏览器窗口<br />
-&gt; CefClientCppToC::Wrap()<br />
-&gt; CefClientCppToC::CefClientCppToC()  设置浏览器的事件处理句柄<br />
-&gt; 进入消息循环<br />
-&gt; 分发消息事件<br />
-&gt; client_get_context_menu_handler()  处理上下文菜单事件<br />
-&gt; CefContextMenuHandlerCppToC::Wrap()<br />
-&gt; CefContextMenuHandlerCppToC::CefContextMenuHandlerCppToC() 设置上下文菜单的过程处理句柄（显示前、点击、消失等）<br />
-&gt; context_menu_handler_on_before_context_menu()  c函数 显示前处理<br />
-&gt; ClientHandler::OnBeforeContextMenu() c++函数 显示前处理</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【CEF3学习】&#8211; 生成IDE的工程文件</title>
		<link>https://blog.z6z8.cn/2022/03/07/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e7%94%9f%e6%88%90ide%e7%9a%84%e5%b7%a5%e7%a8%8b%e6%96%87%e4%bb%b6/</link>
		
		<dc:creator><![CDATA[holdsky]]></dc:creator>
		<pubDate>Mon, 07 Mar 2022 08:17:14 +0000</pubDate>
				<category><![CDATA[CEF]]></category>
		<category><![CDATA[学习笔记]]></category>
		<guid isPermaLink="false">http://blog.z6z8.cn/?p=1175</guid>

					<description><![CDATA[下载下来的CEF压缩包解压后，里面包含CEF接口源码、示例、静态库等资源，并提供cmake脚本文件以生成IDE [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>下载下来的CEF压缩包解压后，里面包含CEF接口源码、示例、静态库等资源，并提供cmake脚本文件以生成IDE工程文件；使用CMake UI来操作这些脚本文件。<br />
首先，填写好CEF解压后的路径（包含CMakeLists.txt的目录）,IDE工程文件的输出路径（可以写和CMakeLists.txt相同的目录）<br />
<img decoding="async" src="/wp-content/uploads/2022/03/1.png" alt="" /></p>
<p>然后，点击<code>Configure</code>按钮，配置IDE参数<br />
<img decoding="async" src="/wp-content/uploads/2022/03/2.png" alt="" /></p>
<p>正常情况下，下图到参数是自动生成的<br />
<img decoding="async" src="/wp-content/uploads/2022/03/3.png" alt="" /></p>
<p>点击<code>Generate</code>按钮，生成IDE工程文件<br />
<img decoding="async" src="/wp-content/uploads/2022/03/4.png" alt="" /></p>
<p>打开IDE工程文件，直接以Debug模式运行<code>cefclient</code>这个项目，可以看到一个十分简单的浏览器页面出现了<img decoding="async" src="/wp-content/uploads/2022/03/5.png" alt="" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>【CEF3学习】&#8211; 下载构建好的版本</title>
		<link>https://blog.z6z8.cn/2022/03/07/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e4%b8%8b%e8%bd%bd%e6%9e%84%e5%bb%ba%e5%a5%bd%e7%9a%84%e7%89%88%e6%9c%ac/</link>
		
		<dc:creator><![CDATA[holdsky]]></dc:creator>
		<pubDate>Mon, 07 Mar 2022 07:54:23 +0000</pubDate>
				<category><![CDATA[CEF]]></category>
		<category><![CDATA[学习笔记]]></category>
		<guid isPermaLink="false">http://blog.z6z8.cn/?p=1171</guid>

					<description><![CDATA[CEF全称Chromium Embedded Framework，是一个基于Google Chromium 的 [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>CEF全称Chromium Embedded Framework，是一个基于Google Chromium 的开源项目。相关资料在https://bitbucket.org/chromiumembedded/cef/wiki/Home 中基本都能找到。</p>
<p>我不选择手动构建，一是因为没有合适的硬件资源，二是构建好的二进制产品可以很方便的从这里下载。<br />
<a href="https://cef-builds.spotifycdn.com/index.html">https://cef-builds.spotifycdn.com/index.html</a></p>
<p>上面这个网站提供包括32/64位以及RAM架构的CPU下的Linux/MacOS/Windows平台的构建产品；<br />
提供的版本有两种，一种是稳定版本（Current Stable Build (Preferred)），一种是Beta版本（Current Beta Build (For Testing)）。</p>
<p>本文选择的是MacOS-64-Standard Distribution版本，<a href="https://cef-builds.spotifycdn.com/cef_binary_97.1.7%2Bg45ce543%2Bchromium-97.0.4692.99_macosx64.tar.bz2">https://cef-builds.spotifycdn.com/cef_binary_97.1.7%2Bg45ce543%2Bchromium-97.0.4692.99_macosx64.tar.bz2</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
