zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    SpringMVC源码分析--HandlerMappings
    你真的懂wait、notify和notifyAll吗
    深入理解DefaultMessageListenerContainer
    起步
    ZOJ 3827 Information Entropy (2014牡丹江区域赛)
    Spring简化配置
    对于一个IE8兼容性问题的反思
    xcode7.1.1不能真机调试ios9.2系统设备的解决方法
    CSS3怎样实现超出指定文本以省略号显示效果
    网易2016年研发project师编程题(2)
  • 原文地址:https://www.cnblogs.com/chechen/p/6122374.html
Copyright © 2011-2022 走看看