关于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 plaincopy
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 plaincopy
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 plaincopy
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. 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 plaincopy
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. new ExampleCefApp);
9.
10. if (CefExecuteProcess(main_args, app.get()) == -1)
11. {
12. CefSettings settings;
13. CefSettingsTraits::init( &settings);
14. true;
15. CefInitialize (main_args, settings, app.get());
16.
17. new ExampleCefHandler();
18.
19. CefWindowInfo info;
20. info.SetAsChild(m_hWnd, CRect(0, 0, 1200, 1200));
21.
22. CefBrowserSettings settings1;
23. "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显示出新浪的页面了(结果如下图)。
















