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:
simple_handler.cpp:
SimpleHandler类继承了CefLifeSpanHandler, 用于管理CefBrowser的生存周期
simple_app.h:
simple_app.cpp:
注意 simple_app的头文件要放在前面, 否则会出现编译错误
添加了这俩个类之后, 我们接下来要做的是初始化cef, 在main函数中添加如下代码:
这里需要注意的是, CefSettings对象, 我们设置了multi_threaded_message_loop=true, 这样设置的目的是,使cef 的browser ui线程和我们程序的线程分离, 我们可以使用duilib的消息循环函数CPaintManagerUI::MessageLoop(), 而不必调用cef的CefRunMessageLoop()。
接下来添加我们的duilib代码:
退出消息循环一定要调用CefShutdown()来关闭cef
在duilib的窗口类的initWindow()中添加如下代码来嵌入cef窗口:
rt是一个RECT对象, 表示你放置cef窗口的区域
这样, 把cef3嵌入到duilib窗口中的工作就基本完成了, 下面就可以设计我们自己需要的功能了:
例如添加一个URL输入窗口, 并跳转到对应的页面, 我们可以添加如下代码:
m_handler是一个SimpleHandler对象, m_pURL是一个duilib的编辑框对象
后退到前一个页面:
调整窗口大小:
加载拖拽的本地html文件:
接一下来, 我们会讲解如何在cef中实现 js 和 c++的交互操作。
注:demo代码中, 需要在OnFinalMessage中处理下退出逻辑:
例如改为如下代码:
先判断下, cef是否关闭了, 再退出消息循环, 以防退出时候崩溃
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是否关闭了, 再退出消息循环, 以防退出时候崩溃
相关文章推荐
- Android Manifest 用法
- Android学习笔记(二九):嵌入浏览器
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 峰回路转,Firefox 浏览器即将重返 iOS 平台
- 回顾 Firefox 历史
- 小白观察:微软释放出其基于 Chromium 的 Edge 浏览器
- 浏览器 cookie 限制
- 玩转浏览器IE7的5个顶级使用技巧
- 字符集导致的浏览器跨站脚本攻击分析
- 更改IE浏览器的图标
- 如何创建ajax对象并兼容多个浏览器
- css ie6 ie7 ff的CSS hack使用技巧
- CSS 浏览器的等宽空格问题解决
- 区分IE6,IE7,firefox的CSS hack
- PHP检测用户是否关闭浏览器的方法
- PHP限制页面只能在微信自带浏览器访问的代码
- asp.net实现获取客户端详细信息
- ASP.NET实现推送文件到浏览器的方法
- 多种浏览器清除缓存的方法小结
- Dom与浏览器兼容性说明