您的位置:首页 > 产品设计 > UI/UE

duilib + cef简单浏览器的demo

2016-06-18 15:57 1616 查看
参考连接:
https://bitbucket.org/chromiumembedded/cef/wiki/Home
自己写的demo地址:
http://download.csdn.net/detail/shuaixingrumo/9556308
关于编译duilib的库和cef库的步骤不详细说了, 网上有很多这样的文章

首先我们要先添加俩个类:

一个是SimpleApp, 用来初始化cef context环境的类, 一个是 SimpleHandler类, 和cef交互主要靠它

simple_handler.h:

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
#define CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_

#include "include/cef_client.h"

#include <list>

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<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 bool DoClose(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);

bool IsClosing() const { return is_closing_; }

CefRefPtr<CefBrowser> GetBrowser(){return m_browser;}

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

CefRefPtr<CefBrowser> m_browser;

bool is_closing_;

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

#endif  // CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_


simple_handler.cpp:

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "simple_handler.h"

#include <sstream>
#include <string>

#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"

namespace {

SimpleHandler* g_instance = NULL;

}  // namespace

SimpleHandler::SimpleHandler()
: is_closing_(false), m_browser(NULL) {
DCHECK(!g_instance);
g_instance = this;
}

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

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

void SimpleHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();

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

bool SimpleHandler::DoClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();

if(m_browser)
is_closing_ = true;
// Allow the close. For windowed browsers this will result in the OS close
// event being sent.
return false;
}

void SimpleHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();

if(m_browser->IsSame(browser))
m_browser = NULL;
}

void SimpleHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) {
CEF_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 << "<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);
}


SimpleHandler类继承了CefLifeSpanHandler, 用于管理CefBrowser的生存周期

simple_app.h:

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
#define CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_

#include "include/cef_app.h"

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

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

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

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

#endif  // CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_


simple_app.cpp:

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "simple_app.h"

#include <string>

#include "simple_handler.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/wrapper/cef_helpers.h"

SimpleApp::SimpleApp() {
}

void SimpleApp::OnContextInitialized() {

}


注意 simple_app的头文件要放在前面, 否则会出现编译错误

添加了这俩个类之后, 我们接下来要做的是初始化cef, 在main函数中添加如下代码:

void* sandbox_info = NULL;
CefMainArgs main_args(hInstance);
CefRefPtr<SimpleApp> app(new SimpleApp);
CefSettings settings;
settings.no_sandbox = true;
settings.multi_threaded_message_loop = true;
CefInitialize(main_args, settings, app.get(), sandbox_info);


这里需要注意的是, CefSettings对象, 我们设置了multi_threaded_message_loop=true, 这样设置的目的是,使cef 的browser ui线程和我们程序的线程分离, 我们可以使用duilib的消息循环函数CPaintManagerUI::MessageLoop(), 而不必调用cef的CefRunMessageLoop()。

接下来添加我们的duilib代码:

CPaintManagerUI::SetInstance(hInstance);
CMainWnd wnd;
wnd.Create(NULL, L"", UI_WNDSTYLE_FRAME | WS_THICKFRAME, WS_EX_ACCEPTFILES);
wnd.ShowWindow();
wnd.CenterWindow();
CPaintManagerUI::MessageLoop();
CefShutdown();


退出消息循环一定要调用CefShutdown()来关闭cef

在duilib的窗口类的initWindow()中添加如下代码来嵌入cef窗口:

CefWindowInfo info;
info.SetAsChild(m_hWnd, rt);

CefBrowserSettings settings;
CefBrowserHost::CreateBrowser(info, m_handler.get(), L"http://www.baidu.com", settings, NULL);


rt是一个RECT对象, 表示你放置cef窗口的区域

这样, 把cef3嵌入到duilib窗口中的工作就基本完成了, 下面就可以设计我们自己需要的功能了:

例如添加一个URL输入窗口, 并跳转到对应的页面, 我们可以添加如下代码:

std::wstring strUrl = m_pURL->GetText();
m_handler->GetBrowser()->GetMainFrame()->LoadURL(strUrl);


m_handler是一个SimpleHandler对象, m_pURL是一个duilib的编辑框对象

后退到前一个页面:

m_handler->GetBrowser()->GoBack();


调整窗口大小:

HWND hwnd = ::FindWindowEx(m_hWnd, NULL, L"CefBrowserWindow", NULL);
::MoveWindow(hwnd, 3, 100, LOWORD(lParam)-6, HIWORD(lParam)-103, TRUE);


加载拖拽的本地html文件:

WCHAR wcFile[MAX_PATH] = {0};
UINT count = DragQueryFile((HDROP)wParam, 0xFFFFFFFF, NULL, 0);
if(count)
{
DragQueryFile((HDROP)wParam, 0, wcFile, MAX_PATH);
wstring str = wcFile;
m_handler->GetBrowser()->GetMainFrame()->LoadURL(str);
m_pURL->SetText(wcFile);
}


接一下来, 我们会讲解如何在cef中实现 js 和 c++的交互操作。

注:demo代码中, 需要在OnFinalMessage中处理下退出逻辑:

例如改为如下代码:

while(m_handler->GetBrowser())
{
Sleep(10);
}
::PostQuitMessage(0);


先判断下, cef是否关闭了, 再退出消息循环, 以防退出时候崩溃
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  duilib cef3 浏览器 demo