Chromium Embedded Framework


關於CEF

近期由於工作需要開始研究了Google的Chromium Embedded Framework(CEF),這是一個基於Google Chromium開源代碼的項目,使用CEF可以很方便的在你自己程序中顯示Web。簡單的調研后發現,現在很多主流的客戶端都使用了CEF來顯示Web頁面:網易雲音樂、QQ、豌豆莢等(安裝目錄下可以找到libcef.dll)。

下載CEF

我使用的是3.1650.1562版本,CEF的發布版本在這里下載http://www.magpcss.net/cef_downloads/,頁面下方的Download List表格中列出的是最新的發布版本(包括Windows、Linux、MacOS平台的32、64位版本)。我下載的是cef_binary_3.1650.1562_windows32,如果表格中的版本不是3.1650.1562,可以點擊 older (deprecated) versions去找到。下載到本地之后解壓縮到本地文件夾(我解壓到了D:\cef_binary_3.1650.1562_windows32),打開文件夾后使用VS2010開打cefclient2010.sln,可以看到兩個項目:cefclient、libcef_dll_wrapper。編譯Debug版本的cefclient項目,確保可以編譯通過,此時會在out目錄下(我的目錄是D:\cef_binary_3.1650.1562_windows32\out\Debug)生成相應的文件,運行cefclient.exe會顯示出Google的頁面。cefclient是如何使用cef的一個例子,具體可以參考項目代碼。

將CEF嵌入到單文檔程序中

在VS2010中,點擊菜單項文件-》新建-》項目,選擇MFC應用程序,項目名稱命名為:CEFBrowser,項目位置根據你上面的解壓縮位置而定,我的是D:\cef_binary_3.1650.1562_windows32,解決方案選擇“添加到解決方案”,點擊“確定”。如下圖所示:
 
 
在“應用程序類型”中選擇“單個文檔”,MFC的使用選擇“在靜態庫中使用MFC”,其余的選項默認,點擊“完成”。可以看到在解決方案中新添加了CEFBrowser項目。
 
 
 
 
首先,將CEFBrowser項目設置為啟動項目。右鍵點擊CEFBrowser打開項目的“屬性頁”,點擊“通用屬性”-》框架和引用-》添加新引用,在彈出的“添加引用”對話框中選擇“libcef_dll_wrapper”項目,點擊“確定”。如下圖所示:
 


 
點擊“確定”退出屬性頁。libcef_dll_wrapper生成靜態庫libcef_dll_wrapper.lib,輸出到cef_binary_3.1650.1562_windows32\out\Debug\lib目
錄下,我們的程序需要加載這個靜態庫,當然你也可以在設置中按照目錄包含它,或者在程序中使用#pragma comment鏈接它。
 
然后,在“配置屬性”-》C/C++-》常規-》附加包含目錄,加入../,因為我們的程序需要inlclude文件夾下的頭文件,include目錄位於上一級目錄。
 
 
其次,將cefclient項目屬性頁中的鏈接器-》常規-》附加庫目錄的內容全部拷貝到CEFBrowser項目的相應位置:
 
 
最后,將cefclient屬性頁的輸入-》附加依賴項中的內容全部拷貝到CEFBrowser項目的相應位置,並且將最后的$(Configuration)\libcef.lib前面加上../改為../$(Configuration)\libcef.lib
 
 
以上工程的環境就配置好了,下面開始添加使用cef的代碼:
 
  • 給CEFBrowser工程添加一個空白的頭文件:ExampleCefApp.h,文件中加入如下代碼:
    [cpp]  view plain  copy
     
    1. #pragma once  
    2. #include "include/cef_app.h"  
    3.   
    4. class ExampleCefApp : public CefApp  
    5. {  
    6. public:  
    7.     ExampleCefApp ()  
    8.     {  
    9.     }  
    10.     virtual ~ExampleCefApp ()  
    11.     {  
    12.     }  
    13.   
    14. private:  
    15.     IMPLEMENT_REFCOUNTING (ExampleCefApp);  
    16. };  
  • 在給CEFBrowser工程添加一個空白的頭文件:ExampleCefHandler.h,文件中加入如下代碼:
    [cpp]  view plain  copy
     
    1. #pragma once  
    2.   
    3. #include "include/cef_client.h"  
    4.   
    5. class ExampleCefHandler : public CefClient,  
    6.     public CefContextMenuHandler,  
    7.     public CefDisplayHandler,  
    8.     public CefDownloadHandler,  
    9.     public CefDragHandler,  
    10.     public CefGeolocationHandler,  
    11.     public CefKeyboardHandler,  
    12.     public CefLifeSpanHandler,  
    13.     public CefLoadHandler,  
    14.     public CefRequestHandler  
    15. {  
    16. public:  
    17.     ExampleCefHandler();  
    18.     virtual ~ExampleCefHandler();  
    19.     CefRefPtr<CefBrowser> GetBrowser();  
    20.   
    21. #pragma region CefClient  
    22.     // since we are letting the base implementations handle all of the heavy lifting,  
    23.     // these functions just return the this pointer  
    24.     virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler () OVERRIDE;  
    25.     virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler () OVERRIDE;  
    26.     virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler () OVERRIDE;  
    27.     virtual CefRefPtr<CefDragHandler> GetDragHandler () OVERRIDE;  
    28.     virtual CefRefPtr<CefGeolocationHandler> GetGeolocationHandler () OVERRIDE;  
    29.     virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler () OVERRIDE;  
    30.     virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler () OVERRIDE;  
    31.     virtual CefRefPtr<CefLoadHandler> GetLoadHandler () OVERRIDE;  
    32.     virtual CefRefPtr<CefRequestHandler> GetRequestHandler () OVERRIDE;  
    33. #pragma endregion // CefClient  
    34.   
    35. #pragma region CefDownloadHandler  
    36.     // this function is virtual and must be implemented; we do nothing in it, so downloading files won't work as the callback function isn't invoked  
    37.     virtual void OnBeforeDownload (CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item, const CefString& suggested_name, CefRefPtr<CefBeforeDownloadCallback> callback);  
    38. #pragma endregion // CefDownloadHandler   
    39.   
    40. #pragma region CefLifeSpanHandler  
    41.     // cache a reference to the browser  
    42.     virtual void OnAfterCreated (CefRefPtr<CefBrowser> browser) OVERRIDE;  
    43.     // release the browser reference  
    44.     virtual void OnBeforeClose (CefRefPtr<CefBrowser> browser) OVERRIDE;  
    45. #pragma endregion // CefLifeSpanHandler    
    46.   
    47. protected:  
    48.     // the browser reference  
    49.     CefRefPtr<CefBrowser> browser;  
    50.   
    51.     // Include the default reference counting implementation.  
    52.     IMPLEMENT_REFCOUNTING (ExampleCefHandler);  
    53.     // Include the default locking implementation.  
    54.     IMPLEMENT_LOCKING (ExampleCefHandler);  
    55. };  
  • 然后給CEFBrowser工程添加一個空白的源文件:ExampleCefHandler.cpp,加入代碼如下:
    [cpp]  view plain  copy
     
    1. #include "stdafx.h"  
    2. #include "ExampleCefHandler.h"  
    3.   
    4.   
    5. ExampleCefHandler::ExampleCefHandler ()  
    6. {  
    7. }  
    8.   
    9. ExampleCefHandler::~ExampleCefHandler ()  
    10. {  
    11. }  
    12.   
    13. CefRefPtr<CefBrowser> ExampleCefHandler::GetBrowser ()  
    14. {  
    15.     return browser;  
    16. }  
    17.   
    18. CefRefPtr<CefContextMenuHandler> ExampleCefHandler::GetContextMenuHandler ()   
    19. {  
    20.     return this;  
    21. }  
    22.   
    23. CefRefPtr<CefDisplayHandler> ExampleCefHandler::GetDisplayHandler ()   
    24. {  
    25.     return this;  
    26. }  
    27.   
    28. CefRefPtr<CefDownloadHandler> ExampleCefHandler::GetDownloadHandler ()   
    29. {  
    30.     return this;  
    31. }  
    32.   
    33. CefRefPtr<CefDragHandler> ExampleCefHandler::GetDragHandler ()   
    34. {  
    35.     return this;  
    36. }  
    37.   
    38. CefRefPtr<CefGeolocationHandler> ExampleCefHandler::GetGeolocationHandler ()  
    39. {  
    40.     return this;  
    41. }  
    42.   
    43. CefRefPtr<CefKeyboardHandler> ExampleCefHandler::GetKeyboardHandler ()   
    44. {  
    45.     return this;  
    46. }  
    47.   
    48. CefRefPtr<CefLifeSpanHandler> ExampleCefHandler::GetLifeSpanHandler ()   
    49. {  
    50.     return this;  
    51. }  
    52.   
    53. CefRefPtr<CefLoadHandler> ExampleCefHandler::GetLoadHandler ()   
    54. {  
    55.     return this;  
    56. }  
    57.   
    58. CefRefPtr<CefRequestHandler> ExampleCefHandler::GetRequestHandler ()   
    59. {  
    60.     return this;  
    61. }  
    62.   
    63. void ExampleCefHandler::OnBeforeDownload (CefRefPtr<CefBrowser> browser,   
    64.     CefRefPtr<CefDownloadItem> download_item,   
    65.     const CefString& suggested_name, CefRefPtr<CefBeforeDownloadCallback> callback)  
    66. {  
    67.     UNREFERENCED_PARAMETER (browser);  
    68.     UNREFERENCED_PARAMETER (download_item);  
    69.     callback->Continue (suggested_name, true);  
    70. }  
    71.   
    72. void ExampleCefHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)   
    73. {  
    74.   
    75.     CefLifeSpanHandler::OnAfterCreated (browser);  
    76. }  
    77.   
    78. void ExampleCefHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)   
    79. {  
    80.     CefLifeSpanHandler::OnBeforeClose (browser);  
    81. }  
  • 切換到“類視圖”,右鍵點擊CCEFBrowserView-》屬性,在屬性對話框中給類CCEFBrowserView添加WM_CREATE的響應函數OnCreate。在CEFBrowserView.cpp文件開頭處加入如下代碼:
    [cpp]  view plain  copy
     
    1. #include "ExampleCefApp.h"  
    2. #include "ExampleCefHandler.h"  
    3.   
    4. #define INVALID_HWND (HWND)INVALID_HANDLE_VALUE  
    5.   
    6. namespace  
    7. {  
    8.     CefRefPtr<ExampleCefHandler> example_cef_handler;  
    9.     HWND application_message_window_handle = INVALID_HWND;  
    10. }  

    OnCreate函數的代碼如下:
    [cpp]  view plain  copy
     
    1. int CCEFBrowserView::OnCreate(LPCREATESTRUCT lpCreateStruct)  
    2. {  
    3.     if (CView::OnCreate(lpCreateStruct) == -1)  
    4.         return -1;  
    5.   
    6.     // TODO:  在此添加您專用的創建代碼  
    7.     CefMainArgs main_args ( AfxGetApp()->m_hInstance );  
    8.     CefRefPtr<ExampleCefApp> app (new ExampleCefApp);  
    9.   
    10.     if (CefExecuteProcess(main_args, app.get()) == -1)  
    11.     {  
    12.         CefSettings settings;  
    13.         CefSettingsTraits::init( &settings);  
    14.         settings.multi_threaded_message_loop = true;  
    15.         CefInitialize (main_args, settings, app.get());  
    16.   
    17.         example_cef_handler = new ExampleCefHandler();  
    18.   
    19.         CefWindowInfo info;  
    20.         info.SetAsChild(m_hWnd, CRect(0, 0, 1200, 1200));  
    21.   
    22.         CefBrowserSettings settings1;  
    23.         CefBrowserHost::CreateBrowser(info, example_cef_handler.get(), CefString ("http://www.sina.com"), setting1, NULL);  
    24.     }  
    25.     return 0;  
    26. }  


至此,所添加的代碼完畢,好了現在編譯工程CEFBrowser,在Debug目錄

(我的路徑是D:\cef_binary_3.1650.1562_windows32\Debug)中確認生成了CEFBrowser.exe,

同時編譯器自動的將需要的一些CEF文件也拷貝到了此文件夾下。此時還不能成功運行CEFBrowser.exe

顯示出頁面,需要將上面我們編譯cefclient項目產生的locales文件夾和cef.pak文件

(D:\cef_binary_3.1650.1562_windows32\out\Debug目錄中)拷貝到Debug目錄下

(提示是否替換,選擇是),好了現在可以運行CEFBrowser.exe顯示出新浪的頁面了(結果如下圖)。



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM