热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何利用CEF3创建一个简单的应用程序(WindowsPlatform)

说明这篇文章主要讲述如何利用CEF3来创建一个简单的应用程序,引用的是1535及以上版本中包含的Cefsimple项目例子。如果想知道关于CEF3更多的使用方法,可以去访问GeneralUs

说明

这篇文章主要讲述如何利用CEF3来创建一个简单的应用程序,引用的是1535及以上版本中包含的 Cefsimple 项目例子。如果想知道关于CEF3更多的使用方法,可以去访问 GeneralUsage.

开始

首先,根据自身所使用的开发平台,可以去 这里 下载对应的发布版本。针对这个教程,我们需要下载1750或者更新的版本。当前支持的平台有Windows, Linux和Mac OS X。每一个版本都包含了当在特定平台上编译特定版本CEF3时所需要的所有文件和资源。您可以通过包含在里边的 REDME.txt 文件或者在Wiki上 GeneralUsage 中的 Getting Started,了解每个发布版本的具体内容和细节。

编译发布版本中的项目

以CEF发布版本为基础开发的应用程序可以使用标准的平台编译工具进行编译执行。包括 Windows 平台下的 Visual Studio, Mac OS X 平台下的 Xcode,  以及 Linux 平台下的 gcc/make。针对平台的不同,项目的编译过程也有些许的不同和要求。

Windows

Windows 平台下编译 Cefsimple 步骤:

1. 用对应的 Visual Studio 版本打开项目解决方案。举个例子,如果你安装的是 Visual Studio 2010, 那么,打开的就是 cesimple2010.sln。

2. 如果你下载的是 x64版本,请确保你选择的是 x64的开发平台。

3. 开始编译。

4. 如果编译通过,那么,在当前解决方案的目录下,将出现“out/Debug”(或者 “out/Release”)文件夹。

5. 执行文件夹下 cefsimple.exe, 确保能正确运行。

加载一个自定义URL

cefsimple项目中默认加载的URL是 google.com,当然,你也可以用自定义的 URL 去替代它,最方便的就是通过命令行搞定。

# Load the local file “c:\example\example.html”
cefsimple.exe
--url=file://c:/example/example.html

除了命令行的方法,也可以通过直接修改在 cefsimple/simple.cpp 文件中的代码,达到你的目的。

# Load the local file “c:\example\example.html”

if (url.empty())
url
= file://c:/example/example.html;

应用程序组成

所有的 CEF 应用程序都有一下主要组成部分:

1. CEF 的动态链接库 。(在 Windows 平台下就是 libcef.dll)

2. 支持库。(ICU, FFMPEG等)

3. 资源。(html/js/css, strings等)

4. 客户端执行文件。(本教程中就是 cefsimple.exe.)

要点(必看)

1. CEF 使用的是多进程。应用程序主进程是浏览器进程,而其他子进程是由 renderer, plugins, GPU等创建。

2. 在 Windows 和 Linux 平台下的执行文件可以被主进程和子进程使用。

3. CEF 中所有进程都可以是多线程的。CEF提供了许多功能和接口在不同的线程中传递任务。

4. 一些回调方法和函数只能在特定的进程或者线程中使用。在你第一次使用新的回调方法或者函数之前,请确保你已经阅读了 API 头文件中源码,看使用要求。

流程分析

cefsimple 应用程序首先初始化CEF,然后创建了一个简单的弹出浏览器窗口。当关闭了所有的浏览器窗口,应用程序就会结束。程序执行流程如下:

1. 系统执行入口点函数(main or wWinMain),并创建浏览器进程。

2. 入口点函数:

1. 创建能够处理进程级别的回调方法的 SimpleApp 实例。

2. 初始化 CEF,进入 CEF 消息循环。

3. 初始化 CEF 之后,调用 SimpleApp::OnContextInitialized() 。这个方法中:

1. 创建单例的 SimpleHandler 。

2. 由 CefBrowserHost::CreateBrowsersync() 方法创建一个浏览器窗口。

4. 所有的浏览器共享 SimpleHandler 实例, 此实例能定制浏览器行为、处理浏览器相关回调方法(life span, loading state, title display等)。

5. 当一个浏览器窗口关闭的时候,调用 SimpleHandler::OnBeforeClose() 。当所有的浏览器窗口全部关闭时,OnBeforeClose() 函数就会执行跳出 CEF 消息循环的行为,退出应用程序。

入口点函数

程序的运行开始于浏览器进程中的入口点函数。这个函数会初始化 CEF 以及所有跟操作系统有关的对象。

Windows

#include 

#include
"cefsimple/simple_app.h"
#include
"include/cef_sandbox_win.h"


// Set to 0 to disable sandbox support.
#define CEF_ENABLE_SANDBOX 1

#if CEF_ENABLE_SANDBOX
// The cef_sandbox.lib static library is currently built with VS2010. It may not
// link successfully with other VS versions.
#pragma comment(lib, "cef_sandbox.lib")
#endif


// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow) {
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

void* sandbox_info = NULL;

#if CEF_ENABLE_SANDBOX
// Manage the life span of the sandbox information object. This is necessary
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
CefScopedSandboxInfo scoped_sandbox;
sandbox_info
= scoped_sandbox.sandbox_info();
#endif

// Provide CEF with command-line arguments.
CefMainArgs main_args(hInstance);

// SimpleApp implements application-level callbacks. It will create the first
// browser instance in OnContextInitialized() after CEF has initialized.
CefRefPtr app(new SimpleApp);

// CEF applications have multiple sub-processes (render, plugin, GPU, etc)
// that share the same executable. This function checks the command-line and,
// if this is a sub-process, executes the appropriate logic.
int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
if (exit_code >= 0) {
// The sub-process has completed so return here.
return exit_code;
}

// Specify CEF global settings here.
CefSettings settings;

#if !CEF_ENABLE_SANDBOX
settings.no_sandbox
= true;
#endif

// Initialize CEF.
CefInitialize(main_args, settings, app.get(), sandbox_info);

// Run the CEF message loop. This will block until CefQuitMessageLoop() is
// called.
CefRunMessageLoop();

// Shut down CEF.
CefShutdown();

return 0;
}

SimpleApp

SimpleApp 负责处理进程级别的回调方法。它会曝露出一些在多进程中共享或者被特定进程使用的接口和方法。CefBrowserProcessHandler 接口,在浏览器进程中调用。还有一个被分离出 CefBrowserProcessHandler 接口(例子项目没有展示)只会在渲染进程中被调用。由于 CefBrowserProcessHandler 不光实现了 CefApp, 同时还有 CefBrowserProcessHandler,所以它的返回值必须是[this]。

// simple_app.h
#include "include/cef_app.h"

class SimpleApp : public CefApp,
public CefBrowserProcessHandler {
public:
SimpleApp();

// CefApp methods:
virtual CefRefPtr GetBrowserProcessHandler()
OVERRIDE {
return this; }

// CefBrowserProcessHandler methods:
virtual void OnContextInitialized() OVERRIDE;

private:
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(SimpleApp);
};


// simple_app.cpp
#include "cefsimple/simple_app.h"

#include
<string>

#include
"cefsimple/simple_handler.h"
#include
"cefsimple/util.h"
#include
"include/cef_browser.h"
#include
"include/cef_command_line.h"

SimpleApp::SimpleApp() {
}

void SimpleApp::OnContextInitialized() {
REQUIRE_UI_THREAD();

// Information used when creating the native window.
CefWindowInfo window_info;

#if defined(OS_WIN)
// On Windows we need to specify certain flags that will be passed to
// CreateWindowEx().
window_info.SetAsPopup(NULL, "cefsimple");
#endif

// SimpleHandler implements browser-level callbacks.
CefRefPtr handler(new SimpleHandler());

// Specify CEF browser settings here.
CefBrowserSettings browser_settings;

std::
string url;

// Check if a "--url=" value was provided via the command-line. If so, use
// that instead of the default URL.
CefRefPtr command_line =
CefCommandLine::GetGlobalCommandLine();
url
= command_line->GetSwitchValue("url");
if (url.empty())
url
= "http://www.google.com";

// Create the first browser window.
CefBrowserHost::CreateBrowserSync(window_info, handler.get(), url,
browser_settings, NULL);
}

SimpleHandler

SimpleHandler 负责处理浏览器级别的回调方法。这些回调方法会在浏览器进程中执行。在这个项目中,针对所有的浏览器使用相同的 CefClient 实例,但是如果你愿意,可以在自己的应用程序中使用不同的 CefClient实例的。

// simple_handler.h
#include "include/cef_client.h"

#include


class SimpleHandler : public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefLoadHandler {
public:
SimpleHandler();
~SimpleHandler();

// Provide access to the single global instance of this object.
static SimpleHandler* GetInstance();

// CefClient methods:
virtual CefRefPtr GetDisplayHandler() OVERRIDE {
return this;
}
virtual CefRefPtr GetLifeSpanHandler() OVERRIDE {
return this;
}
virtual CefRefPtr GetLoadHandler() OVERRIDE {
return this;
}

// CefDisplayHandler methods:
virtual void OnTitleChange(CefRefPtr browser,
const CefString& title) OVERRIDE;

// CefLifeSpanHandler methods:
virtual void OnAfterCreated(CefRefPtr browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr browser) OVERRIDE;

// CefLoadHandler methods:
virtual void OnLoadError(CefRefPtr browser,
CefRefPtr
frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;

// Request that all existing browser windows close.
void CloseAllBrowsers(bool force_close);

private:
// List of existing browser windows. Only accessed on the CEF UI thread.
typedef std::list > BrowserList;
BrowserList browser_list_;

// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(SimpleHandler);
};


// simple_handler.cpp
#include "cefsimple/simple_handler.h"

#include

#include
<string>

#include
"cefsimple/util.h"
#include
"include/cef_app.h"
#include
"include/cef_runnable.h"

namespace {

SimpleHandler
* g_instance = NULL;

}
// namespace

SimpleHandler::SimpleHandler() {
ASSERT(
!g_instance);
g_instance
= this;
}

SimpleHandler::
~SimpleHandler() {
g_instance
= NULL;
}

// static
SimpleHandler* SimpleHandler::GetInstance() {
return g_instance;
}

void SimpleHandler::OnAfterCreated(CefRefPtr browser) {
REQUIRE_UI_THREAD();

// Add to the list of existing browsers.
browser_list_.push_back(browser);
}

void SimpleHandler::OnBeforeClose(CefRefPtr browser) {
REQUIRE_UI_THREAD();

// Remove from the list of existing browsers.
BrowserList::iterator bit = browser_list_.begin();
for (; bit != browser_list_.end(); ++bit) {
if ((*bit)->IsSame(browser)) {
browser_list_.erase(bit);
break;
}
}

if (browser_list_.empty()) {
// All browser windows have closed. Quit the application message loop.
CefQuitMessageLoop();
}
}

void SimpleHandler::OnLoadError(CefRefPtr browser,
CefRefPtr
frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) {
REQUIRE_UI_THREAD();

// Don't display an error for downloaded files.
if (errorCode == ERR_ABORTED)
return;

// Display a load error message.
std::stringstream ss;
ss
<<""
"

Failed to load URL " <string(failedUrl) <<
" with error " <string(errorText) <<" (" < ").

";
frame
->LoadString(ss.str(), failedUrl);
}

void SimpleHandler::CloseAllBrowsers(bool force_close) {
if (!CefCurrentlyOn(TID_UI)) {
// Execute on the UI thread.
CefPostTask(TID_UI,
NewCefRunnableMethod(
this, &SimpleHandler::CloseAllBrowsers,
force_close));
return;
}

if (browser_list_.empty())
return;

BrowserList::const_iterator it
= browser_list_.begin();
for (; it != browser_list_.end(); ++it)
(
*it)->GetHost()->CloseBrowser(force_close);
}


// simple_handler_win.cpp -- Windows-specific code.
#include "cefsimple/simple_handler.h"

#include
<string>
#include


#include
"cefsimple/util.h"
#include
"include/cef_browser.h"

void SimpleHandler::OnTitleChange(CefRefPtr browser,
const CefString& title) {
REQUIRE_UI_THREAD();

CefWindowHandle hwnd
= browser->GetHost()->GetWindowHandle();
SetWindowText(hwnd, std::wstring(title).c_str());
}


// simple_handler_gtk.cc -- Linux-specific code.
#include "cefsimple/simple_handler.h"

#include

#include
<string>

#include
"cefsimple/util.h"
#include
"include/cef_browser.h"

void SimpleHandler::OnTitleChange(CefRefPtr browser,
const CefString& title) {
REQUIRE_UI_THREAD();

GtkWidget
* window = gtk_widget_get_ancestor(
GTK_WIDGET(browser
->GetHost()->GetWindowHandle()),
GTK_TYPE_WINDOW);
std::
string titleStr(title);
gtk_window_set_title(GTK_WINDOW(window), titleStr.c_str());
}


// simple_handler_mac.mm -- OS X-specific code.
#include "cefsimple/simple_handler.h"

#import


#include
"cefsimple/util.h"
#include
"include/cef_browser.h"

void SimpleHandler::OnTitleChange(CefRefPtr browser,
const CefString& title) {
REQUIRE_UI_THREAD();

NSView
* view = (NSView*)browser->GetHost()->GetWindowHandle();
NSWindow
* window = [view window];
std::
string titleStr(title);
NSString
* str = [NSString stringWithUTF8String:titleStr.c_str()];
[window setTitle:str];
}

编译步骤(Windows)

1. 编译 libcef_dll_wrapper 静态库。

2. 编译/链接项目。

1. 源文件:cefsimple_win.cpp, simple_app.cpp, simple_handler.cpp, simple_handler_win.cpp.

2. 链接库:comctl32.lib, shlwapi.lib, rcprt4.lib, libcef_dll_wrapper.lib, libcef.lib, cef_sandbox.lib.  (cef_sandbox.lib 是 sandbox 支持,当前内部仅支持 VS2010, 如果使用其他VS版本,可以将 cefsimple_win.cpp 中 的 CEF_ENABLE_SANDBOX 设置为 0)

3. 将有关的库和资源复制到输出目录。

4. 将 Debug/Release 文件夹下文件复制到输出目录。

输出目录的结构应该如下:

Application/
cefsimple.exe
<= cefsimple application executable
libcef.dll
<= main CEF library
icudt.dll
<= ICU unicode support library
ffmpegsumo.dll
<= HTML5 audio/video support library
libEGL.dll, libGLESv2.dll, …
<= accelerated compositing support libraries
cef.pak, devtools_resources.pak
<= non-localized resources and strings
locales
/
en
-US.pak, … <= locale-specific resources and strings

推荐阅读
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 兆芯X86 CPU架构的演进与现状(国产CPU系列)
    本文详细介绍了兆芯X86 CPU架构的发展历程,从公司成立背景到关键技术授权,再到具体芯片架构的演进,全面解析了兆芯在国产CPU领域的贡献与挑战。 ... [详细]
  • malloc 是 C 语言中的一个标准库函数,全称为 memory allocation,即动态内存分配。它用于在程序运行时申请一块指定大小的连续内存区域,并返回该区域的起始地址。当无法预先确定内存的具体位置时,可以通过 malloc 动态分配内存。 ... [详细]
  • Python多线程详解与示例
    本文介绍了Python中的多线程编程,包括僵尸进程和孤儿进程的概念,并提供了具体的代码示例。同时,详细解释了0号进程和1号进程在系统中的作用。 ... [详细]
  • 我有一个从C项目编译的.o文件,该文件引用了名为init_static_pool ... [详细]
  • 在 CentOS 6.4 上安装 QT5 并启动 Qt Creator 时,可能会遇到缺少 GLIBCXX_3.4.15 的问题。这是由于系统中的 libstdc++.so.6 版本过低。本文将详细介绍如何通过更新 GCC 版本来解决这一问题。 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • MATLAB字典学习工具箱SPAMS:稀疏与字典学习的详细介绍、配置及应用实例
    SPAMS(Sparse Modeling Software)是一个强大的开源优化工具箱,专为解决多种稀疏估计问题而设计。该工具箱基于MATLAB,提供了丰富的算法和函数,适用于字典学习、信号处理和机器学习等领域。本文将详细介绍SPAMS的配置方法、核心功能及其在实际应用中的典型案例,帮助用户更好地理解和使用这一工具箱。 ... [详细]
  • iOS 设备唯一标识获取的高效解决方案与实践
    在iOS 7中,苹果公司再次禁止了对MAC地址的访问,使得开发者无法直接获取设备的物理地址。为了在开发过程中实现设备的唯一标识,苹果推荐使用Keychain服务来存储和管理唯一的标识符。此外,还可以结合其他技术手段,如UUID和广告标识符(IDFA),以确保设备的唯一性和安全性。这些方法不仅能够满足应用的需求,还能保护用户的隐私。 ... [详细]
  • 本文介绍了 Go 语言中的高性能、可扩展、轻量级 Web 框架 Echo。Echo 框架简单易用,仅需几行代码即可启动一个高性能 HTTP 服务。 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 探讨异步 Rust 中多线程代码无法实现并行化的原因及解决方案。 ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • 为了在Hadoop 2.7.2中实现对Snappy压缩和解压功能的原生支持,本文详细介绍了如何重新编译Hadoop源代码,并优化其Native编译过程。通过这一优化,可以显著提升数据处理的效率和性能。此外,还探讨了编译过程中可能遇到的问题及其解决方案,为用户提供了一套完整的操作指南。 ... [详细]
  • 在VS2013中编译FFMPEG时遇到的问题及解决方案
    在使用VS2013编译旧版本FFMPEG库时遇到了一些问题,因为官方并未提供预编译的LIB和DLL文件。由于对Linux环境不熟悉,只能在Windows环境下进行配置和编译。具体步骤如下:首先,下载FFMPEG的源代码;然后,安装必要的编译工具和依赖项;接着,配置Visual Studio 2013的项目设置;最后,解决编译过程中出现的各种错误和警告。通过这些步骤,最终成功编译出所需的FFMPEG库文件。 ... [详细]
author-avatar
mobiledu2502879793
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有