duilib + cef简单浏览器的demo

来源:互联网 发布:nginx 只允许ip访问 编辑:程序博客网 时间:2024/05/16 12:08

参考连接:

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;}  // namespaceSimpleHandler::SimpleHandler()    : is_closing_(false), m_browser(NULL) {  DCHECK(!g_instance);  g_instance = this;}SimpleHandler::~SimpleHandler() {  g_instance = NULL;}// staticSimpleHandler* 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是否关闭了, 再退出消息循环, 以防退出时候崩溃



2 0
原创粉丝点击