cef3嵌入win32无win10标题栏大小窗口,怎么来移动这个cef窗口

Posts - 110,
Articles - 2,
Comments - 204
23:16 by Haippy, ... 阅读,
CEF3 作为一个基于 Chromium 的嵌入式浏览器框架为开发者提供了几个基本的接口类来完成一些基本功能。
CefApp 类介绍
CefApp: 与进程,命令行参数,代理,资源管理相关的回调类,用于让 CEF3 的调用者们定制自己的逻辑。与该类相关的几个函数如下:
int CefExecuteProcess(const CefMainArgs& args, CefRefPtr&CefApp& application);
bool CefInitialize(const CefMainArgs& args, const CefSettings& settings,
CefRefPtr&CefApp& application);
CefExecuteProcess() 和 CefInitialize() 都可以将 CefApp 类的一个对象做为参数传递进来。另外,CefApp 的主要接口如下,其中 OnBeforeCommandLineProcessing 函数在你的程序启动 CEF 和 Chromium 之前给你提供了修改命令行参数的机会;OnRegisterCustomSchemes 用于注册自定义 schemes,剩下的接口用于返回相关回调函数的 Handler。
// Provides an opportunity to view and/or modify command-line arguments before
// processing by CEF and Chromium. The |process_type| value will be empty for
// the browser process. Do not keep a reference to the CefCommandLine object
// passed to this method. mand_line_args_disabled value
// can be used to start with an empty command-line object. Any values
// specified in CefSettings that equate to command-line arguments will be set
// before this method is called. Be cautious when using this method to modify
// command-line arguments for non-browser processes as this may result in
// undefined behavior including crashes.
virtual void OnBeforeCommandLineProcessing(
const CefString& process_type,
CefRefPtr&CefCommandLine& command_line) {
// Provides an opportunity to register custom schemes. Do not keep a reference
// to the |registrar| object. This method is called on the main thread for
// each process and the registered schemes should be the same across all
// processes.
virtual void OnRegisterCustomSchemes(
CefRefPtr&CefSchemeRegistrar& registrar) {
// Return the handler for resource bundle events. If
// CefSettings.pack_loading_disabled is true a handler must be returned. If no
// handler is returned resources will be loaded from pack files. This method
// is called by the browser and render processes on multiple threads.
virtual CefRefPtr&CefResourceBundleHandler& GetResourceBundleHandler() {
return NULL;
// Return the handler for functionality specific to the browser process. This
// method is called on multiple threads in the browser process.
virtual CefRefPtr&CefBrowserProcessHandler& GetBrowserProcessHandler() {
return NULL;
// Return the handler for functionality specific to the render process. This
// method is called on the render process main thread.
virtual CefRefPtr&CefRenderProcessHandler& GetRenderProcessHandler() {
return NULL;
CefClient 类介绍
CefClient: 回调管理类,该类的对象作为参数可以被传递给CefCreateBrowser() 或者 CefCreateBrowserSync() 函数。该类的主要接口如下:
// Return the handler for context menus. If no handler is provided the default
// implementation will be used.
virtual CefRefPtr&CefContextMenuHandler& GetContextMenuHandler() {
return NULL;
// Return the handler for dialogs. If no handler is provided the default
// implementation will be used.
virtual CefRefPtr&CefDialogHandler& GetDialogHandler() {
return NULL;
// Return the handler for browser display state events.
virtual CefRefPtr&CefDisplayHandler& GetDisplayHandler() {
return NULL;
// Return the handler for download events. If no handler is returned downloads
// will not be allowed.
virtual CefRefPtr&CefDownloadHandler& GetDownloadHandler() {
return NULL;
// Return the handler for focus events.
virtual CefRefPtr&CefFocusHandler& GetFocusHandler() {
return NULL;
// Return the handler for geolocation permissions requests. If no handler is
// provided geolocation access will be denied by default.
virtual CefRefPtr&CefGeolocationHandler& GetGeolocationHandler() {
return NULL;
// Return the handler for JavaScript dialogs. If no handler is provided the
// default implementation will be used.
virtual CefRefPtr&CefJSDialogHandler& GetJSDialogHandler() {
return NULL;
// Return the handler for keyboard events.
virtual CefRefPtr&CefKeyboardHandler& GetKeyboardHandler() {
return NULL;
// Return the handler for browser life span events.
virtual CefRefPtr&CefLifeSpanHandler& GetLifeSpanHandler() {
return NULL;
// Return the handler for browser load status events.
virtual CefRefPtr&CefLoadHandler& GetLoadHandler() {
return NULL;
// Return the handler for off-screen rendering events.
virtual CefRefPtr&CefRenderHandler& GetRenderHandler() {
return NULL;
// Return the handler for browser request events.
virtual CefRefPtr&CefRequestHandler& GetRequestHandler() {
return NULL;
// Called when a new message is received from a different process. Return true
// if the message was handled or false otherwise. Do not keep a reference to
// or attempt to access the message outside of this callback.
virtual bool OnProcessMessageReceived(CefRefPtr&CefBrowser& browser,
CefProcessId source_process,
CefRefPtr&CefProcessMessage& message) {
return false;
CefClient 中返回的回调类包括:
CefContextMenuHandler,回调类,主要用于处理 Context Menu 事件。
CefDialogHandler,回调类,主要用来处理对话框事件。
CefDisplayHandler,回调类,处理与页面状态相关的事件,如页面加载情况的变化,地址栏变化,标题变化等事件。
CefDownloadHandler,回调类,主要用来处理文件下载。
CefFocusHandler,回调类,主要用来处理焦点事件。
CefGeolocationHandler,回调类,用于申请 geolocation 权限。
CefJSDialogHandler,回调类,主要用来处理 JS 对话框事件。
CefKeyboardHandler,回调类,主要用来处理键盘输入事件。
CefLifeSpanHandler,回调类,主要用来处理与浏览器生命周期相关的事件,与浏览器对象的创建、销毁以及弹出框的管理。
CefLoadHandler,回调类,主要用来处理浏览器页面加载状态的变化,如页面加载开始,完成,出错等。
CefRenderHandler,回调类,主要用来处在在窗口渲染功能被关闭的情况下的事件。
CefRequestHandler,回调类,主要用来处理与浏览器请求相关的的事件,如资源的的加载,重定向等。admin001很懒,签名啥也没写
在讨论区提问:
有个一个win32的窗口,以WS_POPUPWINDOW形式呈现,然后在这个窗口里面嵌入了一个cef3的子窗口,现在不知道怎么来移动这个无标题栏的窗口了。 RECT GetClientRect(hWnd, &rect); CefWindowInfo windowI...
发表评论:
彩田路彩福大厦,突然发现离我如此的近。 我在彩田南路中深花园
开源中国未来的目标请看 写在 OSC 6 周年即将来临之际,开源中国未来计划 为了实现这个目标,我们还需要更多的人才加入开源中国,我们长期招聘 Java、Ruby、JavaScript 开发工程师和运维工程师,学历不限,工作经...
加入了开源中国社区
还可以输入5字
共 9 张,还能上传 9 张
[选择编程语言]
Apple Swift
Objective-C
JavaScript
Delphi/Pascal
Flash/ActionScript/Flex
WPF/SilverLight
Shell/批处理
设置备注名:
用户尚未登录,点击登录403 Forbidden
403 Forbidden
You don't have permission to access the URL on this server.Powered by Tengine如何利用CEF3创建一个简单的应用程序 (Windows Platform) - 四-儿 - 博客园
随笔 - 111, 文章 - 0, 评论 - 1, 引用 - 0
这篇文章主要讲述如何利用CEF3来创建一个简单的应用程序,引用的是1535及以上版本中包含的 Cefsimple 项目例子。如果想知道关于CEF3更多的使用方法,可以去访问 .
首先,根据自身所使用的开发平台,可以去
下载对应的发布版本。针对这个教程,我们需要下载1750或者更新的版本。当前支持的平台有Windows, Linux和Mac OS X。每一个版本都包含了当在特定平台上编译特定版本CEF3时所需要的所有文件和资源。您可以通过包含在里边的 REDME.txt 文件或者在Wiki上
中的 Getting Started,了解每个发布版本的具体内容和细节。
编译发布版本中的项目
以CEF发布版本为基础开发的应用程序可以使用标准的平台编译工具进行编译执行。包括 Windows 平台下的 Visual Studio, Mac OS X 平台下的 Xcode,  以及 Linux 平台下的 gcc/make。针对平台的不同,项目的编译过程也有些许的不同和要求。
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是 ,当然,你也可以用自定义的 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())
应用程序组成
所有的 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 以及所有跟操作系统有关的对象。
#include &windows.h&
#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&)
// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
lpCmdLine,
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_info = scoped_sandbox.sandbox_info();
// 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&SimpleApp& 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 &= <span style="color: #) {
// The sub-process has completed so return here.
return exit_
// Specify CEF global settings here.
#if !CEF_ENABLE_SANDBOX
settings.no_sandbox = true;
// 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 <span style="color: #;
SimpleApp 负责处理进程级别的回调方法。它会曝露出一些在多进程中共享或者被特定进程使用的接口和方法。CefBrowserProcessHandler 接口,在浏览器进程中调用。还有一个被分离出 CefBrowserProcessHandler 接口(例子项目没有展示)只会在渲染进程中被调用。由于 CefBrowserProcessHandler 不光实现了 CefApp, 同时还有 CefBrowserProcessHandler,所以它的返回值必须是[this]。
// simple_app.h
#include &include/cef_app.h&
class SimpleApp : public CefApp,
public CefBrowserProcessHandler {
SimpleApp();
// CefApp methods:
virtual CefRefPtr&CefBrowserProcessHandler& GetBrowserProcessHandler()
OVERRIDE { return this; }
// CefBrowserProcessHandler methods:
virtual void OnContextInitialized() OVERRIDE;
// 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_
#if defined(OS_WIN)
// On Windows we need to specify certain flags that will be passed to
// CreateWindowEx().
window_info.SetAsPopup(NULL, &cefsimple&);
// SimpleHandler implements browser-level callbacks.
CefRefPtr&SimpleHandler& handler(new SimpleHandler());
// Specify CEF browser settings here.
CefBrowserSettings browser_
std::string
// Check if a &--url=& value was provided via the command-line. If so, use
// that instead of the default URL.
CefRefPtr&CefCommandLine& command_line =
CefCommandLine::GetGlobalCommandLine();
url = command_line-&GetSwitchValue(&url&);
if (url.empty())
// 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 &list&
class SimpleHandler : public CefClient,
public CefDisplayHandler,
public CefLifeSpanHandler,
public CefLoadHandler {
SimpleHandler();
~SimpleHandler();
// Provide access to the single global instance of this object.
static SimpleHandler* GetInstance();
// CefClient methods:
virtual CefRefPtr&CefDisplayHandler& GetDisplayHandler() OVERRIDE {
return this;
virtual CefRefPtr&CefLifeSpanHandler& GetLifeSpanHandler() OVERRIDE {
return this;
virtual CefRefPtr&CefLoadHandler& GetLoadHandler() OVERRIDE {
return this;
// CefDisplayHandler methods:
virtual void OnTitleChange(CefRefPtr&CefBrowser& browser,
const CefString& title) OVERRIDE;
// CefLifeSpanHandler methods:
virtual void OnAfterCreated(CefRefPtr&CefBrowser& browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr&CefBrowser& browser) OVERRIDE;
// CefLoadHandler methods:
virtual void OnLoadError(CefRefPtr&CefBrowser& browser,
CefRefPtr&CefFrame& frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
// Request that all existing browser windows close.
void CloseAllBrowsers(bool force_close);
// List of existing browser windows. Only accessed on the CEF UI thread.
typedef std::list&CefRefPtr&CefBrowser& & BrowserL
BrowserList browser_list_;
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(SimpleHandler);
// simple_handler.cpp
#include &cefsimple/simple_handler.h&
#include &sstream&
#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;
SimpleHandler* SimpleHandler::GetInstance() {
void SimpleHandler::OnAfterCreated(CefRefPtr&CefBrowser& browser) {
REQUIRE_UI_THREAD();
// Add to the list of existing browsers.
browser_list_.push_back(browser);
void SimpleHandler::OnBeforeClose(CefRefPtr&CefBrowser& 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);
if (browser_list_.empty()) {
// All browser windows have closed. Quit the application message loop.
CefQuitMessageLoop();
void SimpleHandler::OnLoadError(CefRefPtr&CefBrowser& browser,
CefRefPtr&CefFrame& frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) {
REQUIRE_UI_THREAD();
// Don't display an error for downloaded files.
if (errorCode == ERR_ABORTED)
// Display a load error message.
ss && &&html&&body bgcolor=\&white\&&&
&&h2&Failed to load URL & && std::string(failedUrl) &&
& with error & && std::string(errorText) && & (& && errorCode &&
&).&/h2&&/body&&/html&&;
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));
if (browser_list_.empty())
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 &windows.h&
#include &cefsimple/util.h&
#include &include/cef_browser.h&
void SimpleHandler::OnTitleChange(CefRefPtr&CefBrowser& 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 &gtk/gtk.h&
#include &string&
#include &cefsimple/util.h&
#include &include/cef_browser.h&
void SimpleHandler::OnTitleChange(CefRefPtr&CefBrowser& 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 &Cocoa/Cocoa.h&
#include &cefsimple/util.h&
#include &include/cef_browser.h&
void SimpleHandler::OnTitleChange(CefRefPtr&CefBrowser& 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.&#160; (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
en-US.pak, … &= locale-specific resources and stringsChromium Embedded Framework 3 - Bare Bones & erikd.blog()
Update (): I have a few updated notes I&ve included at the bottom of this article.
&The Chromium Embedded Framework (CEF) is an open source project founded by Marshall Greenblatt in 2008 to develop a Web browser control based on the Google Chromium project.& (stolen from the )
Over the last few weeks I&ve spent a number of hours reading up on how to integrate CEF into an application.
provides a nice support area where people can ask for help and the source distribution comes with an example application called &cefclient& that uses CEF to show how to build an application with it.
The problem that I had, though, is that while &cefclient& is a nice resource if you&re looking for an advanced implementation on how to integrate CEF as a whole, but if you&re looking to start out with a complete bare-bones implementation that just barely works it&s overkill.
You&re not quite sure where to start and the example in the
page of the wiki is currently either out of date or referencing a different version of CEF than I&m working with.
Once I was able to get the most basic implementation running, I decided it would be good to document how to do it as the resources I was able to find were either out of date or unavailable.
In my case, I wanted to use Chromium Embedded Framework 3 (CEF3).
From what I&ve read, this is the newest way to use CEF to embed Chromium and it&s using the official .
It&s a multi-process implementation (unlike the single-process that CEF1 uses) and sounds like it will be the better supported version going forward.
There are some trade-offs when using this version, though, and you can see those by browsing the CEF project site.
If you want more detail on what any of the classes or functions I&m referencing do, the project has a good . To be honest, at this point I don&t have a complete understanding of how CEF works internally yet, so there are some cases where it&s &just do this because it works&.
The CefClient
Your application&s implementation of the CefClient class is a hook into a number of the lower level functions you need for the browser to interact with the display and for you to interact with the browser.
It enables you to provide your own implementations for many things, such as a way to handle context menus, a way to handle Javascript dialogs, geolocation and others.
Each &subsystem& (as I guess you&d call them) has its own handler that you can implement (such as CefGeolocationHandler for geolocation).
Take a look at the ClientHandler class in the cefclient code that comes with the CEF source to see all your different options, as well as how to implement them.
You don&t need to provide an implementation of them by default, though.
As long as you have a class that inherits from CefClient that implements CEF&s handy reference counting (CefRefPtr) you&re good to go.
There&s a default implementation built-in for many of the systems and the ones that don&t have one aren&t required for a minimal implementation.
Instead of explaining the bare bones implementation of the CefClient line by line, here&s the full implementation since it&s so basic:
// include/bareboneshandler.h
#ifndef BAREBONESHANDLER_H_
#define BAREBONESHANDLER_H_
#include &include/cef_client.h&
class BareBonesHandler : public CefClient {
BareBonesHandler() { }
~BareBonesHandler() { }
// Note that any of the IMPLEMENT_WHATEVER
// macros that come with CEF can (and do) set
// access modifiers, so you'll want them after
// everything else in your class or you may be
// in for a surprise when the access of a member
// isn't what you expect it to be!
IMPLEMENT_REFCOUNTING(BareBonesHandler);
You&ll see the standard header stuff in there along with the full implementation of the class.
I decided not to namespace it because it would be pointless for this example.
There&s an empty constructor and deconstructor, and the only thing actually implemented on the class is the macro provided by CEF to implement the reference counting.
Make note of my comment if you plan on using any of those macros!
For a more advanced version of this, take a look at ClientHandler in the cefclient source.
The Code To Actually Run It!
The next (and only other) part to a bare bones implementation of CEF is the main() method.
In my current implementation I&m running only on Linux, so I&m using
as my toolkit.
As a warning, though, I&ve never used GTK+ before so the code I have may not be the most elegant.
The reason I&m using GTK+ instead of something I&m more familiar with like
is that CEF comes by default with an implementation for GTK+ 2.
Based on some comments I&ve read during my research it should be possible to use another toolkit, but you&d have to write your own implementation of it.
First, we need to include the headers that are needed:
#include &gtk/gtk.h&
#include &include/cef_app.h&
#include &bareboneshandler.h&
gtk.h and bareboneshandler.h are probably obvious, but the cef_app.h one may not be.
CEF has a CefApp class that you can inherit from to customize the global functionality of your implementation but in a bare bones implementation you don&t need it.
The reason cef_app.h is included is because it also defines a couple other functions and classes that we need to run, such as CefExecuteProcess(), CefInitialize() and CefShutdown().
These functions set up CEF and I&ll go over those shortly.
Next is a global reference to the handler class we created:
CefRefPtr&BareBonesHandler& g_
After that we begin the actual main function and create an instance of the CefMainArgs class that allows CEF command line switches to be passed on to CEF:
int main(int argc, char* argv[]) {
CefMainArgs main_args(argc, argv);
Once in the main function, it&s time to either spawn off some additional processes (to support the multi-process model that CEF3 uses) or to just block until it&s time to exit.
The actual functionality of this method is defined in the API docs I mention above:
int exitCode = CefExecuteProcess(main_args, NULL);
if (exitCode &= 0) {
return exitC
Now that the additional process is taken care of, it&s time to intialize CEF itself.
Using the CefInitialize() function we pass in the main_args, an instance of the CefSettings (where you would specify any customized settings if you wanted) as well as an optional CefApp instance:
CefInitialize(main_args, settings, NULL);
Next it&s on to initializing GTK+ and setting up the widgets that will be displayed in the application:
GtkWidget*
GtkWidget*
GtkWidget*
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), &CEF3 Bare Bones&);
// Set the window to 400x400
gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
g_signal_connect(window, &destroy&, G_CALLBACK(destroy), NULL);
The &destroy& signal is connected to a callback method called destroy that I&ve implemented outside the main method to tell CEF to exit out of the message loop and shut down:
void destroy(void) {
// Tells CEF to quit its message loop so the application can exit.
CefQuitMessageLoop();
The next code block is rather long because I wanted to capture the entire context of what&s happening:
CefBrowserSettings browserS
CefWindowI
g_handler = new BareBonesHandler();
info.SetAsChild(hbox);
CefBrowserHost::CreateBrowserSync(info, g_handler.get(),
&&, browserSettings);
CefBrowserHost::CreateBrowserSync(info, g_handler.get(),
&&, browserSettings);
info.SetAsChild(vbox);
CefBrowserHost::CreateBrowserSync(info, g_handler.get(),
&&, browserSettings);
gtk_widget_show_all(window);
In this block, we first define an instance of the CefBrowserSettings.
This (I believe) is where you would provide any browser frame specific settings.
After that, we define an instance of CefWindowInfo.
This is a class that has a per-platform implementation to hook CEF into whatever widget toolkit you&re using.
On Windows it takes MFC window handles, OS X it takes Cocoa and on Linux it takes GTK+.
Before creating any actual browser windows, though, we want to create an instance of our BareBonesHandler that implements CefClient to pass it to each browser.
Once that&s done, it&s time to actually create the browsers!
Using the CefWindowInfo.SetAsChild() method, we specify the widget that the browser will be created into.
For the first two frames we just want them to show up in the hbox GTK+ container, so that&s what&s passed in to SetAsChild().
Next is where the magic happens.
We make a call to CefBrowserHost&s static CreateBrowserSync() method to create the browser window.
We pass in the CefWindowInfo that has the child to create the browser in, a reference to the BareBonesHandler (using CefRefPtr&s get() method to increment the counter), a default URL to load and the settings for the browser to use.
After doing that twice, we set the vertical box as the child to create into using SetAsChild() again and then call CreateBrowserSync() for a third time.
Last of all, we call the GTK+ function to show all the widgets in the window.
At this point there are only two things left to do before your browser is actually up and running!
Those are to call the CefRunMessageLoop() (you don&t call your normal widget toolkit&s loop) and then call CefShutdown().
CefRunMessageLoop() will block until CefQuitMessageLoop() is called (in the destroy method), then it will tell CEF to shut everything down with CefShutdown():
CefRunMessageLoop();
CefShutdown();
That&s it! You should now have all the code you need to use a bare bones version of CEF!
To help pull it all together, here&s the full file of what we just created:
// barebones.cc
#include &gtk/gtk.h&
#include &include/cef_app.h&
#include &bareboneshandler.h&
CefRefPtr&BareBonesHandler& g_
void destroy(void) {
// Tells CEF to quit its message loop so the application can exit.
CefQuitMessageLoop();
int main(int argc, char* argv[]) {
CefMainArgs main_args(argc, argv);
int exitCode = CefExecuteProcess(main_args, NULL);
if (exitCode &= 0) {
return exitC
CefInitialize(main_args, settings, NULL);
GtkWidget*
GtkWidget*
GtkWidget*
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), &CEF3 Bare Bones&);
// Set the window to 400x400
gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
g_signal_connect(window, &destroy&, G_CALLBACK(destroy), NULL);
CefBrowserSettings browserS
CefWindowI
g_handler = new BareBonesHandler();
info.SetAsChild(hbox);
CefBrowserHost::CreateBrowserSync(info, g_handler.get(),
&&, browserSettings);
CefBrowserHost::CreateBrowserSync(info, g_handler.get(),
&&, browserSettings);
info.SetAsChild(vbox);
CefBrowserHost::CreateBrowserSync(info, g_handler.get(),
&&, browserSettings);
gtk_widget_show_all(window);
CefRunMessageLoop();
CefShutdown();
Building and Running
I would be remiss if I didn&t explain how to build the code, though.
There&s one step that wasn&t completely intuitive to me that took me hours upon hours to get working.
Hopefully this post will save you a bunch of time!
Here&s the command to build it with GCC:
g++ -Iinclude -Icef3 -o build/barebones `pkg-config --cflags gtk+-2.0` barebones.cc -Lcef3/bin/linux/x86_64/cef -lcef -lcef_dll_wrapper -Wl,-rpath,. `pkg-config --libs gtk+-2.0`
Update (): Added -Wl,-rpath,. to the command based on feedback from .
You&ll see the standard include directories (I have an include directory and a cef3/include directory to keep things separated), an output of the binary into build/barebones, the GTK+ 2 cflags from pkg-config, and the barebones.cc file we created.
After that is a flag to tell GCC where to find the libraries to link against and lastly the libraries.
Something to note here is that there are two libraries you need to link against (this is where I spent all the time).
The cef library is the obvious one, it&s the shared library with everything in it.
The cef_dll_wrapper, however, is not.
cef_dll_wrapper is a static library that contains the C++ wrapper around the CEF C functions.
Without it, you&ll run into many linking errors.
It&s also good to note that CEF has pretty strict requirements about how the structure of the libraries and includes are set up in your project.
There are some additional libraries and files (libffmpegsumo.so and locales/) for running that you&ll need as well.
I&d highly recommend you take a look at my github repository I mention below to see how I have everything laid out.
It could save you some time.
Once you have it building on your system, it&s time to run it!
Since my project is a dashboard, I&ve been running it straight on X without any kind of window environment (via SSH) with this command:
DISPLAY=:0 LD_LIBRARY_PATH=. xinit ./barebones --no-sandbox
The DISPLAY variable tells X to run it on the primary screen and the LD_LIBRARY_PATH tells it to look in the current directory for any linked libraries.
The &no-sandbox option tells Chromium not to run with the sandbox.
Take a look at
for more info on that.
It&s highly recommended you don&t run it that way in production because it&s a security risk.
When you get it all running, you should be rewarded with:
A Reference Repository
I&ve created a reference project containing all the code I showed above as well as a build of CEF (on the latest version of Arch Linux, 32- and 64-bit) and the include files.
I was hoping it could be a starting point for people new to CEF3 to save a lot of the time and headaches I went through trying to figure everything out.
You can find the repository at: .
At the time this was posted it currently only includes a GTK+ example, but I hope to add more platforms in the future as I work on my CEF-based projects.
A Few Annoyances
I have run into a few annoyances (which could also be called gotchas) with CEF, though.
One of them is that the CEF include files hard-code the &include& directory in their include directives (such as #include &include/cef_app.h&).
This forces me to lay out the project in a certain way.
I would much prefer the include files to be in a cef/ directory, so you could do &cef/cef_app.h& instead since this would allow me to separate out the CEF includes from my project includes.
The way it&s set up now I have to have a completely separate includes directory to do this.
One other annoyance (aside from the fact there&s a libcef_dll_wrapper.a at all) is that cef_dll_wrapper has paths to a number of other objects hard-coded in the compiled library and these paths are (I think) rather weird.
I don&t know if this is a side effect of when I built them, just how GCC does it, or how CEF has it set up.
Anyway, the static library has &../libcef_dll_wrapper/& hard-coded as the path.
It would be nicer if it was in &./libcef_dll_wrapper& so I could have the .so and .a files at one level and the required files another level below those.
They&re rather small annoyances, though, and pretty easy to work around.
In Closing
All in all I&m quite happy and impressed with CEF now that I have it up and running.
I&m glad there&s a way to embed webkit with V8 and all the other nice things Chromium provides into my project without having to write a lot of boilerplate or implementation code to do it.
As I mentioned before, I hope this post saves you a lot of time and that your CEF projects turn out amazing!
Update (): Marshall Greenblatt responded to
about this article on the official CEF forums with some notes that I have wrong in my article.
I intended to get this article and the corresponding code updated from his feedback but I didn&t have time at that point and it was never finished.
Since I see this article is getting traffic at times and I&d still like it to be a resource for anyone needing help, I&ve included his notes below:
Windows uses standard WinAPI HWND handles. There are no MFC dependencies.
You don&t need to call get() when passing a CefRefPtr&& unless the type stored in the CefRefPtr&& changes (for example from MyClient to CefClient).
You can put the CEF header files in whatever directory you like (for example /path/to/cef/include) and use the compiler include path directive to point to the correct location (for example -I/path/to/cef).
The libcef_dll_wrapper.a static library should contain all of the object code (.o files). If it doesn&t then there may be a bug in how we&re creating the static library.
I still intend to update the article but since it&s been so long since I&ve worked with CEF and this code I need to take some time to get acclimated with it again.
Please enable JavaScript to view the

我要回帖

更多关于 win7标题栏透明 的文章

 

随机推荐