赞助

CEF源码编译和生产库的使用

 CEF版本是Branch 2171 开发环境是VS2012


查看一下libcef_dll_wrapper工程属性,确定Code Generation 选择MTD(Debug) 或者MT(Release),这个设置是编译出的静态库是多线程静态链接,在其他工程中使用时,使用者的工程属性也要对应设置MTD或者MT,让二者保持一致,这样保证不会链接出错。

 

然后我们选择ALL_BUILD后Build,如果不出意外应该会报编译错误:

然后上网搜了一下,是编译器把警告当成错误了

参考我之前博客可以解决:http://www.cnblogs.com/chechen/p/6104879.html

 

CEF运行主要依赖的库就是libcef_dll_wrapper.lib和libcef.lib,其中libcef_dll_wrapper.lib是静态库,libcef.lib 动态库。

一、在MFC中嵌入CEF浏览器窗口

 1.第一步

     

 

第二步: 


      

第三步:

    

Finish之后,调整一下对话框的大小,把对话框上的按钮去掉。

第四步:

把include文件夹拷贝到当前目录

第五步:在上一级目录下新建两个目录bin和Lib

第六步:把CEF工程中Resources目录下的文件全部拷贝到bin目录下

第七步:把CEF工程中Debug下除两个.lib文件全部拷贝到bin目录下

第八步:把Debug目录下的libcef.lib文件和libcef_dll_wrapper\\Debug目录下的libcef_dll_wrapper.lib拷贝到Lib文件下

第九步:工程设置

 

 

第十步:在stdafx.h文件中加入队CEF库的引用和用到的头文件


  #include "include/cef_app.h"
  #include "include/cef_client.h"

// 添加引用CEF的库
#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "..\\Lib\\libcef.lib")
#       pragma comment(lib, "..\\Lib\\libcef_dll_wrapper.lib")
#   else
//         Release
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "..\\Lib\\libcef.lib")
#       pragma comment(lib, "..\\Lib\\libcef_dll_wrapper.lib")
#   else
//         Release
#   endif
#endif

 

这时我编译一下,检查引用库是否正常

第十一步:实现我们自己浏览器的CefApp类 

.h文件

 1 #ifndef _CEFBROWSERAPP_H_
 2 #define _CEFBROWSERAPP_H_
 3
 7 class CCefBrowserApp :public CefApp,
 8     public CefBrowserProcessHandler 
 9 {
10 public:
11     CCefBrowserApp(void);
12     ~CCefBrowserApp(void);
13 
14     // CefApp methods:
15     virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
16         OVERRIDE { return this; }
17 
18     // CefBrowserProcessHandler methods:
19     virtual void OnContextInitialized() OVERRIDE;
20 
21 private:
22     // Include the default reference counting implementation.
23     IMPLEMENT_REFCOUNTING(CCefBrowserApp);
24 };
25 
26 #endif //_CEFBROWSERAPP_H_

.cpp文件

 1 #include "stdafx.h"
 2 #include "CefBrowserApp.h"
 3 
 4 
 5 CCefBrowserApp::CCefBrowserApp(void)
 6 {
 7 
 8 }
 9 
10 
11 CCefBrowserApp::~CCefBrowserApp(void)
12 {
13 
14 }
15 
16 
17 void CCefBrowserApp::OnContextInitialized()
18 {
19 
20 }

 

第十二步:按照分析的步骤编写浏览器并嵌入到我们的MFC主窗口中,在InitInstance中初始化cef

 1 /***************************************begin初始化cef*******************************************/
 2 
 3     void* sandbox_info = NULL;
 4     CefMainArgs main_args(AfxGetApp()->m_hInstance);
 5     CefRefPtr<CCefBrowserApp> spApp(new CCefBrowserApp);
 6 
 7     // Execute the secondary process, if any.
 8     int exit_code = CefExecuteProcess(main_args, spApp.get(),sandbox_info);
 9     if (exit_code >= 0)
10         return exit_code;
11     CefSettings cSettings;
12     cSettings.no_sandbox = true;  
13     cSettings.multi_threaded_message_loop = true; 
14     // Execute the secondary process, if any.
15     CefInitialize(main_args, cSettings, spApp.get(),sandbox_info);
16     /***************************************结束初始化cef*******************************************/

第十三步:在对话框OnInitDialog函数中创建浏览器,在创建前我们先实现自己的CefClient类

.h文件

 1 #ifndef _CEFBROWSERHANDLER_H_
 2 #define _CEFBROWSERHANDLER_H_
 3 
 4 #include <list>
 5 
 6 class CCefBrowserHandler: public CefClient,
 7     public CefDisplayHandler,//显示变化事件
 8     public CefLifeSpanHandler,//Browser生命周期
 9     public CefLoadHandler//加载错误事件
10 {
11 public:
12     CCefBrowserHandler(void);
13     ~CCefBrowserHandler(void);
14 
15 public:
16     // CefClient 事件处理器,如果没有对应处理器则默认使用内部处理器
17     virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE;
18     virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE;
19     virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
20 
21 public:
22     // load handler method
23     virtual void OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl) OVERRIDE;
24 
25 public:
26     // display handler meethod
27     virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
28     virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
29     virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
30 public:
31     // own method of cef browser event handler
32     void CloseAllBrowser(bool bForceClose = true);
33 protected:
34     typedef std::list<CefRefPtr<CefBrowser> > BrowserList;
35     BrowserList  m_browser_list;
36 
37     IMPLEMENT_REFCOUNTING(CCefBrowserHandler);
38 
39 };
40 #endif //_CEFBROWSERHANDLER_H_

.cpp文件

  1 #include "stdafx.h"
  2 #include "CefBrowserHandler.h"
  3 #include <sstream>
  4 #include <string>
  5 #include "include/base/cef_bind.h"
  6 #include "include/views/cef_browser_view.h"
  7 #include "include/views/cef_window.h"
  8 #include "include/wrapper/cef_closure_task.h"
  9 #include "include/wrapper/cef_helpers.h"
 10 
 11 CCefBrowserHandler::CCefBrowserHandler(void)
 12 {
 13 
 14 }
 15 
 16 
 17 CCefBrowserHandler::~CCefBrowserHandler(void)
 18 {
 19 
 20 }
 21 
 22 CefRefPtr<CefDisplayHandler> CCefBrowserHandler::GetDisplayHandler() 
 23 {
 24     return this;
 25 }
 26 
 27 CefRefPtr<CefLifeSpanHandler> CCefBrowserHandler::GetLifeSpanHandler()
 28 {
 29     return this;
 30 }
 31 
 32 CefRefPtr<CefLoadHandler> CCefBrowserHandler::GetLoadHandler()
 33 {
 34     return this;
 35 }
 36 
 37 
 38 void CCefBrowserHandler::OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, ErrorCode errorCode, 
 39                                           const CefString& errorText, const CefString& failedUrl)
 40 {
 41     CEF_REQUIRE_UI_THREAD();
 42     if (ERR_ABORTED == errorCode)
 43         return ;
 44 
 45     std::stringstream ss;
 46     ss << "<html><body bgcolor=\"white\">"
 47         "<h2>Failed to load URL " << std::string(failedUrl) <<
 48         " with error " << std::string(errorText) << " (" << errorCode <<
 49         ").</h2></body></html>";
 50     frame->LoadString(ss.str(), failedUrl);
 51 }
 52 
 53 void CCefBrowserHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)
 54 {
 55     CEF_REQUIRE_UI_THREAD();
 56     m_browser_list.push_back(browser);
 57 }
 58 
 59 bool CCefBrowserHandler::DoClose(CefRefPtr<CefBrowser> browser)
 60 {
 61     CEF_REQUIRE_UI_THREAD();
 62     if (1 == m_browser_list.size())
 63     {
 64     }
 65     return false;
 66 }
 67 
 68 void CCefBrowserHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
 69 {
 70     CEF_REQUIRE_UI_THREAD();
 71     for (BrowserList::iterator bit = m_browser_list.begin(); bit != m_browser_list.end(); ++bit) 
 72     {
 73         if ((*bit)->IsSame(browser)) {
 74             m_browser_list.erase(bit);
 75             break;
 76         }
 77     }
 78 
 79     if (m_browser_list.empty()) 
 80     {
 81         CefQuitMessageLoop();
 82     }
 83 }
 84 
 85 void CCefBrowserHandler::CloseAllBrowser(bool force_close) 
 86 {
 87     if (!CefCurrentlyOn(TID_UI)) 
 88     {
 89         CefPostTask(TID_UI,base::Bind(&CCefBrowserHandler::CloseAllBrowser, this, force_close));
 90         return;
 91     }
 92 
 93     if (m_browser_list.empty())
 94         return;
 95 
 96     BrowserList::const_iterator it = m_browser_list.begin();
 97     for (; it != m_browser_list.end(); ++it)
 98     {
 99         (*it)->GetHost()->CloseBrowser(force_close);
100     }
101 }

在OnInitDialog()函数中创建浏览器

    //开始创建浏览器
    CRect rtBody;

    GetWindowRect(&rtBody);

    CefWindowInfo cefWindowInfo;

    cefWindowInfo.SetAsChild(GetSafeHwnd(), rtBody);

    CefBrowserSettings browserSetting;

    CefRefPtr<CCefBrowserHandler> objEventHandler(new CCefBrowserHandler());

    CefBrowserHost::CreateBrowser(cefWindowInfo, objEventHandler.get(), _T("http://www.baidu.com"), browserSetting, NULL);

第十三步:关闭主窗口时,关闭浏览器

给对话框添加WM_DESTROY消息响应

 

void CMFCCefDemoDlg::OnDestroy()
{

    CDialogEx::OnDestroy();

    // TODO: Add your message handler code here

    CefShutdown();
}

MFCDemo转载:http://blog.csdn.net/lixiang987654321/article/details/52174121

二、在Win32窗口里嵌入CEF浏览器窗口

第一步:新建Win32项目

  

第二步:使用默认

  

第三步:修改工程属性

第四步:在stdafx.h中加入 CEF库

#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "..\\Lib\\libcef.lib")
#       pragma comment(lib,"..\\Lib\\libcef_dll_wrapper.lib")
#   else
#       //Release
#   endif
#else
#   ifdef _UNICODE
#        //Multi_Debug
#   else
#        //Multi_Release
#   endif
#endif

第五步:在工程目录下新建两个目录,分别为bin和Lib

第六步:把CEF工程中Resources目录下的文件全部拷贝到bin目录下

第七步:把CEF工程中Debug下除两个.lib文件全部拷贝到bin目录下

第八步:把Debug目录下的libcef.lib文件和libcef_dll_wrapper\\Debug目录下的libcef_dll_wrapper.lib拷贝到Lib文件下

第九步:工程设置-->指定生成的exe文件的路径

第十步:实现自己的CefApp

.h

 1 #ifndef _MYCEFAPP_H_
 2 #define _MYCEFAPP_H_
 3 
 4 #include "include/cef_app.h"
 5 
 6 class CMyCefApp: public CefApp,
 7     public CefBrowserProcessHandler {
 8 
 9 public:
10     CMyCefApp(void);
11     ~CMyCefApp(void);
12 
13     // CefApp methods:
14     virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
15         OVERRIDE { return this; }
16 
17     // CefBrowserProcessHandler methods:
18     virtual void OnContextInitialized() OVERRIDE;
19 
20 private:
21     // Include the default reference counting implementation.
22     IMPLEMENT_REFCOUNTING(CMyCefApp);
23 };
24 
25 
26 #endif//_MYCEFAPP_H_

.cpp

 1 #include "stdafx.h"
 2 #include "MyCefApp.h"
 3 
 4 
 5 CMyCefApp::CMyCefApp(void)
 6 {
 7 
 8 }
 9 
10 
11 CMyCefApp::~CMyCefApp(void)
12 {
13 
14 }
15 
16 
17 void CMyCefApp::OnContextInitialized() {
18 
19 }

第十二步:实现自己的Handler类

.h

 1 #pragma once
 2 #include "include/cef_client.h"  
 3 #include <list>  
 4 #include <string>  
 5 using std::wstring;
 6 
 7 class CCefHandler:  
 8     public CefClient,
 9     public CefDisplayHandler,
10     public CefLifeSpanHandler,
11     public CefLoadHandler
12 {
13 public:
14     CCefHandler();
15 
16     virtual ~CCefHandler(void);
17 
18     // Provide access to the single global instance of this object.
19     static CCefHandler* GetInstance();
20 
21     // CefClient methods:
22     virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
23         return this;
24     }
25     virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
26         return this;
27     }
28     virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
29         return this;
30     }
31 
32     // CefDisplayHandler methods:
33     virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
34         const CefString& title) OVERRIDE;
35 
36     // CefLifeSpanHandler methods:
37     virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
38     virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
39     virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
40 
41     // CefLoadHandler methods:
42     virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
43         CefRefPtr<CefFrame> frame,
44         ErrorCode errorCode,
45         const CefString& errorText,
46         const CefString& failedUrl) OVERRIDE;
47 
48     // Request that all existing browser windows close.
49     //void CloseAllBrowsers(bool force_close);
50 
51     bool IsClosing() const { return is_closing_; }
52 
53     CefRefPtr<CefBrowser> GetBrowser(){return m_browser;}  
54 
55 private:
56     // List of existing browser windows. Only accessed on the CEF UI thread.
57     //typedef std::list<CefRefPtr<CefBrowser> > BrowserList;
58     // BrowserList browser_list_;
59 
60     CefRefPtr<CefBrowser> m_browser; 
61 
62     bool is_closing_;
63 
64     // Include the default reference counting implementation.
65     IMPLEMENT_REFCOUNTING(CCefHandler);
66 }

.cpp

  1 #include "stdafx.h"
  2 #include "CefHandler.h"
  3 #include <sstream>
  4 #include <string>
  5 
  7 #include "include/cef_app.h"
  8 #include "include/cef_runnable.h"
  9 #include "include/wrapper/cef_closure_task.h"
    #include "include/wrapper/cef_helpers.h"
 10 namespace {
 11 
 12     CCefHandler* g_instance = NULL;
 13 
 14 }  // namespace
 15 
 16 CCefHandler::CCefHandler()
 17     : is_closing_(false)
 18     ,m_browser(NULL){   20         g_instance = this;
 21 }
 22 
 23 CCefHandler::~CCefHandler() {
 24     g_instance = NULL;
 25 }
 26 
 27 // static
 28 CCefHandler* CCefHandler::GetInstance() {
 29     return g_instance;
 30 }
 31 
 32 void CCefHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
 33     REQUIRE_UI_THREAD();
 34 
 35     // Add to the list of existing browsers.
 36     //browser_list_.push_back(browser);
 37 
 38     m_browser = browser;
 39 }
 40 
 41 bool CCefHandler::DoClose(CefRefPtr<CefBrowser> browser) {
 42     CEF_REQUIRE_UI_THREAD();
 43 
 44     // Closing the main window requires special handling. See the DoClose()
 45     // documentation in the CEF header for a detailed destription of this
 46     // process.
 47     //if (browser_list_.size() == 1)
 48     if(m_browser) 
 49     {
 50         // Set a flag to indicate that the window close should be allowed.
 51         is_closing_ = true;
 52     }
 53 
 54     // Allow the close. For windowed browsers this will result in the OS close
 55     // event being sent.
 56     return false;
 57 }
 58 
 59 void CCefHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
 60                   const CefString& title)
 61 {
 62 
 63 }
 64 
 65 void CCefHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
 66     CEF_REQUIRE_UI_THREAD();
 67 
 68     // Remove from the list of existing browsers.
 69     //BrowserList::iterator bit = browser_list_.begin();
 70     //for (; bit != browser_list_.end(); ++bit) {
 71     //  if ((*bit)->IsSame(browser)) {
 72     //    browser_list_.erase(bit);
 73     //    break;
 74     //  }
 75     //}
 76 
 77     //if (browser_list_.empty()) {
 78     //  // All browser windows have closed. Quit the application message loop.
 79     //  CefQuitMessageLoop();
 80     //}
 81 
 82     if(m_browser->IsSame(browser))  
 83         m_browser = NULL;
 84 }
 85 
 86 void CCefHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
 87                                 CefRefPtr<CefFrame> frame,
 88                                 ErrorCode errorCode,
 89                                 const CefString& errorText,
 90                                 const CefString& failedUrl)
 91 {
 92     CEF_REQUIRE_UI_THREAD();
 93 
 94     // Don't display an error for downloaded files.
 95     if (errorCode == ERR_ABORTED)
 96         return;
 97 
 98     // Display a load error message.
 99     std::stringstream ss;
100     ss << "<html><body bgcolor=\"white\">"
101     "<h2>Failed to load URL " << std::string(failedUrl) <<
102     " with error " << std::string(errorText) << " (" << errorCode <<
103     ").</h2></body></html>";
104     frame->LoadString(ss.str(), failedUrl);
105 }

第十二步:初始化CEF

 1 /***************************************begin初始化cef*******************************************/
 2 
 3     void* sandbox_info = NULL;
 4     CefMainArgs main_args(hInstance);
 5     CefRefPtr<SimpleApp> spApp(new SimpleApp);
 6 
 7     // Execute the secondary process, if any.
 8     int exit_code = CefExecuteProcess(main_args, spApp.get(),sandbox_info);
 9     if (exit_code >= 0)
10         return exit_code;
11     CefSettings cSettings;
12     cSettings.no_sandbox = true;  
13     cSettings.multi_threaded_message_loop = true; 
14 
15     CefInitialize(main_args, cSettings, spApp.get(),sandbox_info);
16     /***************************************结束初始化cef*******************************************/

 

第十三步:在WM_CREATE消息出创建CEF浏览器窗口

 先定义一个全局的Handler对象指针 

CefRefPtr<CCefHandler> g_handler;

 

 1  . . . . . . . 
 2     case WM_CREATE:  
 3         {  
 4             g_handler=new CCefHandler();
 5 
 6 
 7             RECT rect;  
 8             ::GetClientRect(hWnd, &rect);  
 9             CefWindowInfo info;  
10             info.SetAsChild(hWnd, rect);  
11 
12             CefBrowserSettings settings1;  
13             CefBrowserHost::CreateBrowser(info, g_handler.get(), CefString ("http://www.baidu.com"), settings1, NULL); 
14 
15             return 0;
16         }
17  . . . . . . .     

至此你运行就可以看到效果了。。。

 

最后关闭,我们要在WM_CLOSE消息出做处理:

    case WM_CLOSE:  
        if (g_handler.get() && !g_handler->IsClosing()) {
            CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
            if (browser.get()) {
                // Notify the browser window that we would like to close it. This
                // will result in a call to ClientHandler::DoClose() if the
                // JavaScript 'onbeforeunload' event handler allows it.
                browser->GetHost()->CloseBrowser(false);

                // Cancel the close.
                return 0;
            }
        }
        DestroyWindow(hWnd);
        // Allow the close.
        break;

 

最后程序退出时时要关闭CEF

三、CEF嵌入到Duilib窗口中

工程配置参考前面两种

1.实现自己的APP类

.h

 1 #ifndef _CEFBROWSERAPP_H_
 2 #define _CEFBROWSERAPP_H_
 3 #include "include/cef_app.h"
 4 
 5 class CCefBrowserApp
 6     : public CefApp
 7     , public CefBrowserProcessHandler
 8 {
 9 public:
10     CCefBrowserApp();
11 
12     virtual ~CCefBrowserApp();
13 
14 public:
15     virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()OVERRIDE { return this; };
16 
17 public:
18     // CefBrowserProcessHandler methods:
19     virtual void OnContextInitialized();
20 
21 protected:
22 
23     IMPLEMENT_REFCOUNTING(CCefBrowserApp);
24 };
25 #endif //_CEFBROWSERAPP_H_

.cpp

 1 #include "CefBrowserApp.h"
 2 #include "stdafx.h"
 3 
 4 
 5 CCefBrowserApp::CCefBrowserApp()
 6 {
 7 }
 8 
 9 CCefBrowserApp::~CCefBrowserApp()
10 {
11 }
12 
13 
14 void CCefBrowserApp::OnContextInitialized()
15 {
16     // do nothing here, because we will create browser in my own dialog
17 }

2.实现自己的Handler类

.h

 1 #ifndef _CEFBROWSEREVENTHANDLER_H_
 2 #define _CEFBROWSEREVENTHANDLER_H_
 3 #include "include/cef_client.h"  
 4 #include "include/base/cef_lock.h" //线程安全
 5 
 6 
 7 class CCefBrowserEventHandler
 8     : public CefClient
 9     , public CefDisplayHandler            // 显示变化事件
10     , public CefLoadHandler                // 加载错误事件
11     , public CefLifeSpanHandler            // 声明周期事件
12 {
13 public:
14     CCefBrowserEventHandler();
15 
16     virtual ~CCefBrowserEventHandler();
17 
18 public:
19     // CefClient 事件处理器,如果没有对应处理器则默认使用内部处理器
20     virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE;
21     virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE;
22     virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
23 
24 public:    
25     // display handler method
26     virtual void OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) OVERRIDE;
27 
28 public:
29     // load handler method
30     virtual void OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, 
31         ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl) OVERRIDE;
32 
33 public:
34     // display handler meethod
35     virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
36     virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
37     virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
38 
39     bool IsClosing() const { return m_bIsClosing; }
40 
41     CefRefPtr<CefBrowser> GetBrowser(){return m_Browser;} 
42 
43 protected:
44 
45     CefRefPtr<CefBrowser> m_Browser; 
46 
47     bool m_bIsClosing;
48 
49     IMPLEMENT_REFCOUNTING(CCefBrowserEventHandler);
50     //由于CEF采用多线程架构,有必要使用锁和闭包来保证在多不同线程安全的传递数据。IMPLEMENT_LOCKING定义提供了Lock()和Unlock()方法以及AutoLock对象来保证不同代码块同步访问
51     IMPLEMENT_LOCKING(CCefBrowserEventHandler);//必须包含#include "include/base/cef_lock.h" 
52 };
53 
54 #endif//_CEFBROWSEREVENTHANDLER_H_

.cpp

 1 #include "CefBrowserEventHandler.h"
 2 #include "stdafx.h"
 3 #include <sstream>
 4 #include <string>
 5 #include "include/cef_app.h"
 6 #include "include/wrapper/cef_closure_task.h"
 7 #include "include/wrapper/cef_helpers.h"
 8 
 9 
10 CCefBrowserEventHandler::CCefBrowserEventHandler(CMainFrameWnd* pMainFrame)
11     :m_bIsClosing(false)
12 {
13 
14 }
15 
16 CCefBrowserEventHandler::~CCefBrowserEventHandler()
17 {
18 
19 }
20 
21 CefRefPtr<CefDisplayHandler> CCefBrowserEventHandler::GetDisplayHandler()
22 {
23     return this;
24 }
25 
26 CefRefPtr<CefLifeSpanHandler> CCefBrowserEventHandler::GetLifeSpanHandler()
27 {
28     return this;
29 }
30 
31 CefRefPtr<CefLoadHandler> CCefBrowserEventHandler::GetLoadHandler() 
32 {
33     return this;
34 }
35 
36 void CCefBrowserEventHandler::OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title) 
37 {
38     
39 }
40 
41 void CCefBrowserEventHandler::OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, ErrorCode errorCode, 
42                                           const CefString& errorText, const CefString& failedUrl) 
43 {
44     CEF_REQUIRE_UI_THREAD();
45     if (ERR_ABORTED == errorCode)
46         return ;
47 
48     std::stringstream ss;
49     ss <<    "<html><body bgcolor=\"white\">"
50             "<h2>Failed to load URL " << std::string(failedUrl) <<
51             " with error " << std::string(errorText) << " (" << errorCode <<
52             ").</h2></body></html>";
53     frame->LoadString(ss.str(), failedUrl);
54 }
55 
56 void CCefBrowserEventHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) 
57 {
58     CEF_REQUIRE_UI_THREAD();
59 
60     AutoLock lock_scope(this);
61 
62      m_Browser = browser;
63 
64 }
65 
66 bool CCefBrowserEventHandler::DoClose(CefRefPtr<CefBrowser> browser)
67 {
68     CEF_REQUIRE_UI_THREAD();
69 
70     AutoLock lock_scope(this);
71 
72 
73     if(m_Browser) 
74     {
75         // Set a flag to indicate that the window close should be allowed.
76         m_bIsClosing = true;
77     }
78 
79     return false;
80 }
81 
82 void CCefBrowserEventHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) 
83 {
84     CEF_REQUIRE_UI_THREAD();
85 
86     AutoLock lock_scope(this);
87 
88     if(m_Browser->IsSame(browser))  
89         m_Browser = NULL;
90 }

 3.在入口函数处初始化CEF

 1 // Duilib_Login.cpp : 定义应用程序的入口点。
 2 //
 3 #include "CefBrowserApp.h"
 4 #include "MainFrameWnd.h"
 5 
 6 int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR    lpCmdLine, int       nCmdShow)
 7 {
 8     CPaintManagerUI::SetInstance(hInstance);
 9     CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath() + _T("CefDemo"));
10 
11 
12     HRESULT Hr = ::CoInitialize(NULL);
13     if (FAILED(Hr)) return 0;
14 
15     /***************************************begin初始化cef*******************************************/
16 
17     void* sandbox_info = NULL;
18     CefMainArgs main_args(hInstance);
19     CefRefPtr<CCefBrowserApp> spApp(new CCefBrowserApp);
20 
21     // Execute the secondary process, if any.
22     int exit_code = CefExecuteProcess(main_args, spApp.get(),sandbox_info);
23     if (exit_code >= 0)
24         return exit_code;
25     CefSettings cSettings;
26     cSettings.no_sandbox = true;  
27     cSettings.multi_threaded_message_loop = true; 
28     // Execute the secondary process, if any.
29     CefInitialize(main_args, cSettings, spApp.get(),sandbox_info);
30     /***************************************结束初始化cef*******************************************/
31 
32 
33     CMainFrameWnd*  pMain = new CMainFrameWnd;
34     pMain->Create(NULL, _T("MainFrameWnd"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE | WS_EX_ACCEPTFILES);
35     pMain->CenterWindow();
36     pMain->ShowWindow(TRUE);
37 
38     if (!cSettings.multi_threaded_message_loop) {
39         // Run the CEF message loop. This function will block until the application
40         // recieves a WM_QUIT message.
41         CefRunMessageLoop();
42     }
43     else {
44         DuiLib::CPaintManagerUI::MessageLoop();
45     }
46 
47     CefShutdown();
48 
49     delete pMain;
50     ::CoUninitialize();
51     return 0;
52 }

 

4.在CMainFrameWnd窗口类中定义一个Handler的成员变量

.........

private:
    CefRefPtr<CCefBrowserEventHandler> m_handler;

在CMainFrameWnd初始化列表中构造Handler对象

CMainFrameWnd::CMainFrameWnd()
    :m_handler(new CCefBrowserEventHandler())
{

}

 

5.在虚函数InitWindow()中创建CEF浏览器

void CMainFrameWnd::InitWindow()
{
    RECT rc;
    ::GetClientRect(this->GetHWND(),&rc);

    rc.top    += 28;
    rc.left   += 1;
    rc.right  += -1;
    rc.bottom += -1;

    CefWindowInfo info;  
    info.SetAsChild(*this, rc);

    TCHAR tszModule[MAX_PATH + 1] = { 0 };
    ::GetModuleFileName(NULL, tszModule, MAX_PATH); 
    ::PathRemoveFileSpec(tszModule);

    wstring url =tszModule;
    url+=L"\\JS C++.html";

    CefBrowserSettings settings1;  
    CefBrowserHost::CreateBrowser(info, m_handler.get(), CefString ("http://www.baidu.com"), settings1, NULL);  //打开百度
    //CefBrowserHost::CreateBrowser(info, m_handler.get(), CefString (url), settings1, NULL);  //打开自己写的html
}

6.duilib窗口关闭时需要重写LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) 这个虚函数,在这个虚函数中关闭CEF浏览器

LRESULT CMainFrameWnd::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{

    if (m_handler && !m_handler->IsClosing()) {
//第一次响应WM_CLOSE消息时
        CefRefPtr<CefBrowser> browser = m_handler->GetBrowser();
        if (browser.get()) {
            // Notify the browser window that we would like to close it. This
            // will result in a call to ClientHandler::DoClose() if the
            // JavaScript 'onbeforeunload' event handler allows it.
            browser->GetHost()->CloseBrowser(false);

            // Cancel the close.
            return 0;
        }
    }
//第二次响应WM_CLOSE消息时
    ::PostQuitMessage(1L);
    return 0;
}

7.如果想让浏览器随着窗口大小变化自适应还需要重写LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)这个虚函数

LRESULT CMainFrameWnd::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
    WindowImplBase::OnSize(uMsg,wParam,lParam,bHandled);

    if (m_handler != NULL){  
        CefRefPtr<CefBrowser> browser = m_handler->GetBrowser();  
        if (browser){  
            CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle(); 

            RECT rt;
            ::GetClientRect(m_hWnd, &rt);

            int cx = rt.right - rt.left -2;

            int cy = rt.bottom - rt.top -2;

            ::MoveWindow(hwnd, 1, 28, cx, cy, TRUE);  
        }  
    } 

    return 0;
}

8.按照这个流程走下来,可以正常显示,先看一下效果图

同时看一下进程个数:

大家应该注意到上面标注红颜色的三行代码,我在刚开始嵌入时,把这三行代码忘了没写,就出现一个问题,点"X"关闭,程序正常退出了,但有个窗口进程没退出,桌面上留下一个空白窗口,资源管理器中有显示一个进程没退出。

 

后来反复检查,加上那三行代码后,程序正常退出了,最后看看那三行代码的意思

///
// This function should be called from the application entry point function to
// execute a secondary process. It can be used to run secondary processes from
// the browser client executable (default behavior) or from a separate
// executable specified by the CefSettings.browser_subprocess_path value. If
// called for the browser process (identified by no "type" command-line value)
// it will return immediately with a value of -1. If called for a recognized
// secondary process it will block until the process should exit and then return
// the process exit code. The |application| parameter may be empty. The
// |windows_sandbox_info| parameter is only used on Windows and may be NULL (see
// cef_sandbox_win.h for details).
///
/*--cef(api_hash_check,optional_param=application,
        optional_param=windows_sandbox_info)--*/
int CefExecuteProcess(const CefMainArgs& args,
                      CefRefPtr<CefApp> application,
                      void* windows_sandbox_info);

但是加载本地的html文件,就是没写那三行代码,也不出现上面的问题,感觉很奇怪

9.Debug模式和Release模式配置

  首先 在bin目录下放release版的 libcef.dll

  对于链接cef的lib,在Debug模式下加载Debug的libcef.lib和libcef_dll_wrapper.lib,Release加载Release的libcef.lib和ibcef_dll_wrapper.lib

#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "..\\Lib\\DuiLib_ud.lib")
#       pragma comment(lib, "..\\Lib\\Debug\\libcef.lib")
#       pragma comment(lib, "..\\Lib\\Debug\\libcef_dll_wrapper.lib")
#   else
#       pragma comment(lib, "..\\Lib\\DuiLib_d.lib")
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "..\\Lib\\DuiLib_u.lib")
#       pragma comment(lib, "..\\Lib\\Release\\libcef.lib")
#       pragma comment(lib, "..\\Lib\\Release\\libcef_dll_wrapper.lib")
#   else
#       pragma comment(lib, "..\\Lib\\DuiLib.lib")
#   endif
#endif

这样配置  我们Debug调试 或者发布Release  程序都正常运行

点击下载:CEF嵌入DuilibDemo

posted @ 2016-12-01 16:08  车臣  阅读(6180)  评论(1编辑  收藏  举报