热门标签 | 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

推荐阅读
  • 深入解析Linux下的I/O多路转接epoll技术
    本文深入解析了Linux下的I/O多路转接epoll技术,介绍了select和poll函数的问题,以及epoll函数的设计和优点。同时讲解了epoll函数的使用方法,包括epoll_create和epoll_ctl两个系统调用。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
  • 通过Anaconda安装tensorflow,并安装运行spyder编译器的完整教程
    本文提供了一个完整的教程,介绍了如何通过Anaconda安装tensorflow,并安装运行spyder编译器。文章详细介绍了安装Anaconda、创建tensorflow环境、安装GPU版本tensorflow、安装和运行Spyder编译器以及安装OpenCV等步骤。该教程适用于Windows 8操作系统,并提供了相关的网址供参考。通过本教程,读者可以轻松地安装和配置tensorflow环境,以及运行spyder编译器进行开发。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • 本文分析了Wince程序内存和存储内存的分布及作用。Wince内存包括系统内存、对象存储和程序内存,其中系统内存占用了一部分SDRAM,而剩下的30M为程序内存和存储内存。对象存储是嵌入式wince操作系统中的一个新概念,常用于消费电子设备中。此外,文章还介绍了主电源和后备电池在操作系统中的作用。 ... [详细]
  • 本文介绍了NetCore WebAPI开发的探索过程,包括新建项目、运行接口获取数据、跨平台部署等。同时还提供了客户端访问代码示例,包括Post函数、服务器post地址、api参数等。详细讲解了部署模式选择、框架依赖和独立部署的区别,以及在Windows和Linux平台上的部署方法。 ... [详细]
  • Mono为何能跨平台
    概念JIT编译(JITcompilation),运行时需要代码时,将Microsoft中间语言(MSIL)转换为机器码的编译。CLR(CommonLa ... [详细]
  •     这里使用自己编译的hadoop-2.7.0版本部署在windows上,记得几年前,部署hadoop需要借助于cygwin,还需要开启ssh服务,最近发现,原来不需要借助cy ... [详细]
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社区 版权所有