Windows上使用CEF嵌入基于chrome内核浏览器小例
来源:互联网 发布:淘宝的css初始化代码 编辑:程序博客网 时间:2024/06/06 00:36
CEF出来很久了,使用的也很广泛的,QQ里面很多地方都是嵌入的CEF浏览器(个人资料、微博、查找……),网上的资料也挺多的,大家可以搜搜看。
首先是下载CEF代码编译,通过里面的那两个例子你也可以依葫芦画瓢的。官方下载地址:http://cefbuilds.com/
这里推荐一个很详细的解说:http://www.cnblogs.com/think/archive/2011/10/06/CEF-Introduce.html
重载CEF的各种“消息”处理类,当你需要自己处理或者自定义这些消息时,才需要重载它们,重载后一定要重写相应的虚函数返回this指针。估计内部是有这些个回调类对象指针,不返回this的话默认就是NULL了,就会执行内部默认的那套机制。
#pragma once#include "include/cef_client.h"#include <list>#include <string>using std::wstring;class CCefHandler :public CefClient, public CefDisplayHandler, public CefLifeSpanHandler,public CefLoadHandler,public CefRequestHandler,public CefContextMenuHandler,public CefDownloadHandler{public:CCefHandler(const wstring& strUrl=L"");virtual ~CCefHandler();//自定义方法CefRefPtr<CefBrowser> GetBrowser() { return m_pBrowser; }CefRefPtr<CefFrame>GetMainFram() { return m_pBrowser.get()?m_pBrowser->GetMainFrame():NULL; }HWNDGetBrowserHostWnd() { return m_pBrowser.get()?m_pBrowser->GetHost()->GetWindowHandle():NULL; }voidSetHomePage(const wstring& strUrl) { m_strHomePage=strUrl; }const wstring& GetHomePage()const { return m_strHomePage; }wstring GetLoadingUrl();voidNavigate(const wstring& strUrl);voidCreateBrowser(HWND hParentWnd, const RECT& rect);boolIsClosing() const { return m_bIsClose; } //凡是继承了的处理功能都在这里返回this指针virtual CefRefPtr<CefDisplayHandler>GetDisplayHandler(){ return this; }virtual CefRefPtr<CefLifeSpanHandler>GetLifeSpanHandler(){ return this; }virtual CefRefPtr<CefLoadHandler>GetLoadHandler(){ return this; }virtual CefRefPtr<CefContextMenuHandler>GetContextMenuHandler(){ return this; }virtual CefRefPtr<CefDownloadHandler>GetDownloadHandler(){ return this; } // CefDisplayHandler methods: virtual void OnTitleChange(CefRefPtr<CefBrowser> browser, const CefString& title); virtual void OnAddressChange(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& url); virtual bool OnTooltip(CefRefPtr<CefBrowser> browser, CefString& text); virtual void OnStatusMessage(CefRefPtr<CefBrowser> browser, const CefString& value); // CefLifeSpanHandler methods: virtual bool OnBeforePopup(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \ const CefString& target_url, const CefString& target_frame_name, const CefPopupFeatures& popupFeatures, \ CefWindowInfo& windowInfo, CefRefPtr<CefClient>& client, CefBrowserSettings& settings, \ bool* no_javascript_access); virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser); virtual bool DoClose(CefRefPtr<CefBrowser> browser); virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser); // CefLoadHandler methods: virtual void OnLoadStart(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame); virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode); virtual void OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl); // Request that all existing browser windows close. void CloseAllBrowsers(bool force_close); // virtual bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \ CefRefPtr<CefRequest> request, bool is_redirect) { //return true; return false; } virtual bool OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request) { return false; } //菜单处理 virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \ CefRefPtr<CefContextMenuParams> params, CefRefPtr<CefMenuModel> model); virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \ CefRefPtr<CefContextMenuParams> params, int command_id, EventFlags event_flags); //下载处理 virtual void OnBeforeDownload( CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item, \ const CefString& suggested_name, CefRefPtr<CefBeforeDownloadCallback> callback); virtual void OnDownloadUpdated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item, \ CefRefPtr<CefDownloadItemCallback> callback);private:typedef std::list<CefRefPtr<CefBrowser> > BrowserList;BrowserList browser_list_;CefRefPtr<CefBrowser>m_pBrowser;boolm_bIsClose;wstringm_strHomePage;static intm_nBrowserCount;// Include the default reference counting implementation.IMPLEMENT_REFCOUNTING(CCefHandler);IMPLEMENT_LOCKING(CCefHandler);};
对应的实现代码:
#include "stdafx.h"#include "CefHandler.h"#include <sstream>#include "util.h"#include "../include/cef_app.h"#include "../include/cef_runnable.h"intCCefHandler::m_nBrowserCount = 0;CCefHandler::CCefHandler( const wstring& strUrl/*=L""*/ ): m_bIsClose(false) , m_strHomePage(strUrl){}CCefHandler::~CCefHandler() {}void CCefHandler::CloseAllBrowsers(bool force_close) {if (!CefCurrentlyOn(TID_UI)) {// Execute on the UI thread.CefPostTask(TID_UI, NewCefRunnableMethod(this, &CCefHandler::CloseAllBrowsers, force_close));return;} if (browser_list_.empty()) return; BrowserList::const_iterator it = browser_list_.begin(); for (; it != browser_list_.end(); ++it) (*it)->GetHost()->CloseBrowser(force_close);}wstring CCefHandler::GetLoadingUrl(){CefRefPtr<CefFrame> pMainFram=GetMainFram();return pMainFram.get()?pMainFram->GetURL():L"";}void CCefHandler::Navigate( const wstring& strUrl ){CefRefPtr<CefFrame> pMainFram=GetMainFram();if ( pMainFram.get() )pMainFram->LoadURL(strUrl.c_str());}void CCefHandler::CreateBrowser( HWND hParentWnd, const RECT& rect ){CefWindowInfo info;CefBrowserSettings settings;static wchar_t* pCharset = L"GB2312";settings.default_encoding.str = pCharset;settings.default_encoding.length = wcslen(pCharset);info.SetAsChild(hParentWnd, rect);CefBrowserHost::CreateBrowser(info, this, m_strHomePage.c_str(), settings, NULL);}//****************************************************//菜单加载接口void CCefHandler::OnBeforeContextMenu( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \ CefRefPtr<CefContextMenuParams> params, CefRefPtr<CefMenuModel> model ){//在这里,我添加了自己想要的菜单cef_context_menu_type_flags_t flag = params->GetTypeFlags();if ( flag & CM_TYPEFLAG_PAGE ){//普通页面的右键消息model->SetLabel(MENU_ID_BACK, L"后退");model->SetLabel(MENU_ID_FORWARD, L"前进");model->SetLabel(MENU_ID_VIEW_SOURCE, L"查看源代码");model->SetLabel(MENU_ID_PRINT, L"打印");model->SetLabel(MENU_ID_RELOAD, L"刷新");model->SetLabel(MENU_ID_RELOAD_NOCACHE, L"强制刷新");model->SetLabel(MENU_ID_STOPLOAD, L"停止加载");model->SetLabel(MENU_ID_REDO, L"重复");}if ( flag & CM_TYPEFLAG_EDITABLE){//编辑框的右键消息model->SetLabel(MENU_ID_UNDO, L"撤销");model->SetLabel(MENU_ID_REDO, L"重做");model->SetLabel(MENU_ID_CUT, L"剪切");model->SetLabel(MENU_ID_COPY, L"复制");model->SetLabel(MENU_ID_PASTE, L"粘贴");model->SetLabel(MENU_ID_DELETE, L"删除");model->SetLabel(MENU_ID_SELECT_ALL, L"全选");}}bool CCefHandler::OnContextMenuCommand( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \ CefRefPtr<CefContextMenuParams> params, int command_id, EventFlags event_flags ){return false;}//****************************************************//网页加载状态回调接口void CCefHandler::OnLoadStart( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame ){}void CCefHandler::OnLoadEnd( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode ){//CefRefPtr<CefV8Context> v8 = frame->GetV8Context();}void CCefHandler::OnLoadError(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \ ErrorCode errorCode, const CefString& errorText, const CefString& failedUrl) {REQUIRE_UI_THREAD();// Don't display an error for downloaded files.if (errorCode == ERR_ABORTED)return;// Display a load error message.std::wstringstream ss;//std::wstring ss << L"<html><body bgcolor=\"white\">"L"<h2>Failed to load URL " << std::wstring(failedUrl) <<L" with error " << std::wstring(errorText) << L" (" << errorCode <<L").</h2></body></html>"<<'\0';frame->LoadString(ss.str(), failedUrl);}//****************************************************//状态改变回调接口void CCefHandler::OnTitleChange( CefRefPtr<CefBrowser> browser, const CefString& title ){}void CCefHandler::OnAddressChange( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& url ){}bool CCefHandler::OnTooltip( CefRefPtr<CefBrowser> browser, CefString& text ){return false;}void CCefHandler::OnStatusMessage( CefRefPtr<CefBrowser> browser, const CefString& value ){}//****************************************************//网页生命周期回调接口bool CCefHandler::OnBeforePopup( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, \const CefString& target_url, const CefString& target_frame_name, const CefPopupFeatures& popupFeatures, \CefWindowInfo& windowInfo, CefRefPtr<CefClient>& client, CefBrowserSettings& settings, \bool* no_javascript_access ){//这里使用默认浏览器打开网页,避免CEF重新创建窗口ShellExecute(NULL, L"open", target_url.c_str(), NULL, NULL, SW_SHOW);//return false;//创建新窗口return true; //禁止创建新的窗口}void CCefHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {REQUIRE_UI_THREAD();// Add to the list of existing browsers.browser_list_.push_back(browser);AutoLock scopLock(this);if ( ! m_pBrowser.get() )m_pBrowser=browser;m_nBrowserCount++;}bool CCefHandler::DoClose(CefRefPtr<CefBrowser> browser) {REQUIRE_UI_THREAD();// Closing the main window requires special handling. See the DoClose()// documentation in the CEF header for a detailed destription of this// process.if (browser_list_.size() == 1) {// Set a flag to indicate that the window close should be allowed.m_bIsClose = true;}// Allow the close. For windowed browsers this will result in the OS close// event being sent.return false;}void CCefHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {REQUIRE_UI_THREAD();// Remove from the list of existing browsers.BrowserList::iterator bit = browser_list_.begin();for (; bit != browser_list_.end(); ++bit) {if ((*bit)->IsSame(browser)) {browser_list_.erase(bit);break;}}if (browser_list_.empty()) {// All browser windows have closed. Quit the application message loop.CefQuitMessageLoop();}}void CCefHandler::OnBeforeDownload( CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item, \const CefString& suggested_name, CefRefPtr<CefBeforeDownloadCallback> callback ){int i=0;}void CCefHandler::OnDownloadUpdated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefDownloadItem> download_item, \CefRefPtr<CefDownloadItemCallback> callback ){//取消CEF内部下载文件,使用默认浏览器打开链接去下载,下载过程就不需要我们关心了,毕竟不是做浏览器callback->Cancel();CefString strUrl = download_item->GetURL();ShellExecute(NULL, L"open", strUrl.c_str(), NULL, NULL, SW_SHOW);int i = 0;}
然后是实现CefApp类的重载,没有实际的处理功能,在此忽略。
使用时,创建一个win32项目,然后修改WinMain函数:
CefRefPtr<CCefHandler> g_handler;int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){ // TODO: 在此放置代码。CefMainArgs main_args(hInstance);CefRefPtr<CCefAppEx> app(new CCefAppEx);int exit_code = CefExecuteProcess(main_args, app.get());if (exit_code >= 0) {return exit_code;}CefSettings settings;settings.single_process = true;//settings.multi_threaded_message_loop = true;CefInitialize(main_args, settings, app.get());//if ( strCmd.size() == 0 )HACCEL hAccelTable;// 初始化全局字符串LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_CEFDEMO, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// 执行应用程序初始化:if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CEFDEMO));CefRunMessageLoop();CefShutdown();return 0;}消息处理主要是创建、销毁CEF对象,窗口大小改变时通知CEF窗口等:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;switch (message){case WM_CREATE:{//http://blog.csdn.net/wongson/article/details/6210854g_handler=new CCefHandler(L"www.qq.com");RECT rect;::GetClientRect(hWnd, &rect);g_handler->CreateBrowser(hWnd, rect);break;}case WM_COMMAND:wmId = LOWORD(wParam);wmEvent = HIWORD(wParam);// 分析菜单选择:switch (wmId){case IDM_EXIT:DestroyWindow(hWnd);break;default: break;}break;case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO: 在此添加任意绘图代码...EndPaint(hWnd, &ps);break;case WM_SIZE:{if ( wParam == SIZE_MINIMIZED || NULL == g_handler|| NULL == g_handler->GetBrowserHostWnd() )break;HWND hBrowserWnd=g_handler->GetBrowserHostWnd();RECT rect;::GetClientRect(hWnd, &rect);::MoveWindow(hBrowserWnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);break;}case WM_CLOSE:{if ( g_handler.get() && !g_handler->IsClosing() ){wstring strUrl=g_handler->GetLoadingUrl();CefRefPtr<CefBrowser> pBrowser=g_handler->GetBrowser();if ( pBrowser.get() )pBrowser->GetHost()->CloseBrowser(true);}break;}default: break;}return DefWindowProc(hWnd, message, wParam, lParam);}编译,运行程序,一个简单的网页就出来了,加载速度比IE那垃圾快多了,关键是不用理会兼容性问题了。
最后记得带上CEF的一大堆DLL,这个是必须的,如果网页需要播放视频,需要新建一个plugins文件夹,放入视频播放插件NPSWF32.dll。
需要链接的CEF动态链接库:
#ifdef _DEBUG#pragma comment(lib, "..\\LibCef\\Debug\\libcef")#pragma comment(lib, "..\\LibCef\\Debug\\libcef_dll_wrapper")#else#pragma comment(lib, "..\\LibCef\\Release\\libcef")#pragma comment(lib, "..\\LibCef\\Release\\libcef_dll_wrapper")#endif
感觉有所帮助,欢迎打赏(微信扫码)
5 0
- Windows上使用CEF嵌入基于chrome内核浏览器小例
- WinForm嵌入Chrome内核浏览器
- 嵌入Chrome cef之完整版(本教程基于cef1)
- 嵌入Chrome cef之完整版(本教程基于cef1)
- MFC嵌入浏览器框架CEF
- 基于CEF内核的简单浏览器实现(***)
- 嵌入Chrome cef到MFC CView
- 多文档嵌入Chrome CEF求教
- 嵌入Chrome cef到MFC CView
- 嵌入Chrome cef到MFC CView
- MFC对话框应用程序中谷歌CEF浏览器内核的使用
- MFC对话框应用程序中谷歌CEF浏览器内核的使用
- MFC对话框应用程序中谷歌CEF浏览器内核的使用
- CEF中文教程(google chrome浏览器控件) -- CEF简介
- CEF中文教程(google chrome浏览器控件) -- CEF编译
- CEF中文教程(google chrome浏览器控件) -- CEF简介
- CEF中文教程(google chrome浏览器控件) -- CEF简介
- CEF中文教程(google chrome浏览器控件) -- CEF简介
- CSS Sprites技术及其优化
- 学习反射机制 - 工厂模式
- iOS学习笔记(十六)——数据库操作(使用FMDB)
- php调用sphinx提示failed to send client protocol version
- HTTP协议中 POST和GET的区别和注意事项
- Windows上使用CEF嵌入基于chrome内核浏览器小例
- 科技前沿(1)-石墨烯 在中国、美国、英国、欧盟、韩国、日本的发展情况
- Spring_aop_annotation
- iOS学习笔记(十五)——数据库操作(SQLite)
- java持久层框架分析
- C语言陷阱---数据溢出和类型转换
- 定制个性化App 引领企业跨入互联网时代
- Android之触摸手势检测GestureDetector使用详解
- CSDN爬虫