在mfc單文檔程序中加入cef: 1.在BOOL CtestCEFApp::InitInstance()中初始化cef HINSTANCE hInst = GetModuleHandle(NULL); CefMainArgs main_args(hInst); m_cefApp = new ClientApp(); //cef默認啓動四個進程,分別是瀏覽器主進程,渲染進程,GPU進程,插件進程,如果不是主進程則直接退出 //AfxMessageBox(L"CefExecuteProcess"); int exit_code = CefExecuteProcess(main_args, m_cefApp.get(), NULL); if (exit_code >= 0) return exit_code; //設置cef參數 CString szCEFCache; CString szPath; INT nLen = GetTempPath( 0, NULL ) + 1; GetTempPath( nLen, szPath.GetBuffer( nLen )); szCEFCache.Format( _T("%scache\0\0"), szPath ); CefSettings settings; //settings.no_sandbox = TRUE; //settings.multi_threaded_message_loop = FALSE; CefString(&settings.cache_path) = szCEFCache; //CefSettingsTraits::init( &cSettings); //cSettings.multi_threaded_message_loop = false; m_bCEFInitialized = CefInitialize(main_args, settings,m_cefApp.get(), NULL); //初始化自定義協議 scheme_test::InitTest(); 2.創建瀏覽器窗口 BOOL ClientApp::CreateBrowser(HWND hWnd, CRect rect, LPCTSTR pszURL) { CefBrowserSettings settings; CefWindowInfo info; info.SetAsChild( hWnd, rect ); std::string url = "test://test/html1.html"; return CefBrowserHost::CreateBrowser( info, m_cefHandler.get(), url, settings, NULL ); } 3.資源文件加載 namespace scheme_test { // Implementation of the factory for for creating schema handlers. class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory { public: // Return a new scheme handler instance to handle the request. virtual CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, const CefString& scheme_name, CefRefPtr<CefRequest> request) OVERRIDE { return NULL; } IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory); }; //此方法在ClientApp的虛函數中被調用 void RegisterCustomSchemes(CefRefPtr<CefSchemeRegistrar> registrar, std::vector<CefString>& cookiable_schemes) { registrar->AddCustomScheme("test", true, false, false);//註冊一個新的協議test } //初始化時調用 void InitTest() { CefRegisterSchemeHandlerFactory("test", "test", new ClientSchemeHandlerFactory());//註冊一個新的域名,並且新建一個可以處理此域名請求的類 } } // namespace scheme_test 4.兩個關鍵的類 class CWebClient : public CefClient , public CefLifeSpanHandler , public CefRequestHandler { public: CMyWebBrowser m_wndBrowser; public: CWebClient(void){} virtual ~CWebClient(void){} virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() { return this; } virtual CefRefPtr<CefRequestHandler> GetRequestHandler() { return this; } //virtual bool DoClose( CefRefPtr<CefBrowser> browser ); //virtual void OnBeforeClose( CefRefPtr<CefBrowser> browser ); virtual void OnAfterCreated( CefRefPtr<CefBrowser> browser ); //此處處理接收到的message virtual bool OnProcessMessageReceived( CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message ); //此處加載本地html資源 virtual CefRefPtr<CefResourceHandler> GetResourceHandler( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request ); private: bool ParseTestUrl(const std::string& url, std::string* file_name, std::string* mime_type); public: IMPLEMENT_REFCOUNTING(CWebClient); IMPLEMENT_LOCKING(CWebClient); }; class ClientApp: public CefApp ,public CefBrowserProcessHandler ,public CefRenderProcessHandler { public: ClientApp(void); ClientApp(HWND hWnd); ~ClientApp(void); virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() OVERRIDE { return this; } virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler()OVERRIDE { return this; } //此處處理js和c++調用 virtual void OnContextCreated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context ); virtual void OnContextInitialized() OVERRIDE; //此處要<span style="font-family: Arial, Helvetica, sans-serif;">註冊一個新的協議test</span> virtual void OnRegisterCustomSchemes( CefRefPtr<CefSchemeRegistrar> registrar ); BOOL CreateBrowser(HWND hWnd, CRect rect, LPCTSTR pszURL); public: CefRefPtr<CWebClient> m_cefHandler; private: IMPLEMENT_REFCOUNTING(ClientApp); }; 5.c++和js相互調用 第一種: class CefV8ExtensionHandler : public CefV8Handler { public: CefV8ExtensionHandler(){} ~CefV8ExtensionHandler(){} virtual bool Execute( const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception ); IMPLEMENT_REFCOUNTING(CefV8ExtensionHandler); }; void ClientApp::OnContextCreated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context ) { CefRefPtr<CefV8Value> obj = context->GetGlobal(); CefRefPtr<CefV8Handler> handler = new CefV8ExtensionHandler(); obj->SetValue("test", CefV8Value::CreateFunction("test", handler), V8_PROPERTY_ATTRIBUTE_READONLY); } bool CefV8ExtensionHandler::Execute( const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception ) { if (name == "test") { std::string arg1 = arguments[0]->GetStringValue(); //MessageBoxA(NULL, arg1.c_str(), NULL, NULL); retval = CefV8Value::CreateString(arg1); CefRefPtr<CefBrowser> browser = CefV8Context::GetCurrentContext()->GetBrowser(); ASSERT(browser.get()); CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("test"); browser->SendProcessMessage(PID_BROWSER, message); return true; } return false; } 第二種: std::string app_code = "var app;" "if (!app)" " app = {};" "(function() {" " app.sendMessage = function(name, arguments) {" " native function sendMessage();" " return sendMessage(name, arguments);" " };" " app.setMessageCallback = function(name, callback) {" " native function setMessageCallback();" " return setMessageCallback(name, callback);" " };" " app.removeMessageCallback = function(name) {" " native function removeMessageCallback();" " return removeMessageCallback(name);" " };" "})();"; CefRegisterExtension("v8/app", app_code, new ClientAppExtensionHandler(this)); 6.自定義標題欄需要子類化瀏覽器窗口方能接收到消息 class CMyWebBrowser : public CWnd { DECLARE_DYNCREATE(CMyWebBrowser) public: CMyWebBrowser(void); virtual ~CMyWebBrowser(void); protected: DECLARE_MESSAGE_MAP() public: afx_msg LRESULT OnNcHitTest(CPoint point); }; LRESULT CMyWebBrowser::OnNcHitTest(CPoint point) { CRect rc; GetClientRect(&rc); rc.top = rc.top; rc.left = rc.left; rc.right = rc.right; rc.bottom = 20; ClientToScreen(&rc); CPoint screenpoint(point); ScreenToClient(&screenpoint); if (rc.PtInRect(point)) { AfxGetApp()->GetMainWnd()->PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(screenpoint.x, screenpoint.y)); return 0; } else return CWnd::OnNcHitTest(point); } void CWebClient::OnAfterCreated( CefRefPtr<CefBrowser> browser ) { HWND hWnd = browser->GetHost()->GetWindowHandle(); HWND hChildWnd = ::GetNextWindow(hWnd, GW_CHILD ); m_wndBrowser.SubclassWindow(hChildWnd); CefLifeSpanHandler::OnAfterCreated(browser); } 7.消息循環 int CtestCEFApp::ExitInstance() { if( m_bCEFInitialized ) { m_bCEFInitialized = false; m_cefApp = NULL; CefShutdown(); } return CWinAppEx::ExitInstance(); } BOOL CtestCEFApp::PumpMessage() { if( m_bCEFInitialized ) CefDoMessageLoopWork(); return CWinAppEx::PumpMessage(); } --------------------- 本文來自 lls2012 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/lls2012/article/details/47976101?utm_source=copy
https://blog.csdn.net/lls2012/article/details/47976101
在mfc單文檔程序中加入cef: 1.在BOOL CtestCEFApp::InitInstance()中初始化cef HINSTANCE hInst = GetModuleHandle(NULL); CefMainArgs main_args(hInst); m_cefApp = new ClientApp(); //cef默認啓動四個進程,分別是瀏覽器主進程,渲染進程,GPU進程,插件進程,如果不是主進程則直接退出 //AfxMessageBox(L"CefExecuteProcess"); int exit_code = CefExecuteProcess(main_args, m_cefApp.get(), NULL); if (exit_code >= 0) return exit_code; //設置cef參數 CString szCEFCache; CString szPath; INT nLen = GetTempPath( 0, NULL ) + 1; GetTempPath( nLen, szPath.GetBuffer( nLen )); szCEFCache.Format( _T("%scache\0\0"), szPath ); CefSettings settings; //settings.no_sandbox = TRUE; //settings.multi_threaded_message_loop = FALSE; CefString(&settings.cache_path) = szCEFCache; //CefSettingsTraits::init( &cSettings); //cSettings.multi_threaded_message_loop = false; m_bCEFInitialized = CefInitialize(main_args, settings,m_cefApp.get(), NULL); //初始化自定義協議 scheme_test::InitTest(); 2.創建瀏覽器窗口 BOOL ClientApp::CreateBrowser(HWND hWnd, CRect rect, LPCTSTR pszURL) { CefBrowserSettings settings; CefWindowInfo info; info.SetAsChild( hWnd, rect ); std::string url = "test://test/html1.html"; return CefBrowserHost::CreateBrowser( info, m_cefHandler.get(), url, settings, NULL ); } 3.資源文件加載 namespace scheme_test { // Implementation of the factory for for creating schema handlers. class ClientSchemeHandlerFactory : public CefSchemeHandlerFactory { public: // Return a new scheme handler instance to handle the request. virtual CefRefPtr Create(CefRefPtr browser, CefRefPtr frame, const CefString& scheme_name, CefRefPtr request) OVERRIDE { return NULL; } IMPLEMENT_REFCOUNTING(ClientSchemeHandlerFactory); }; //此方法在ClientApp的虛函數中被調用 void RegisterCustomSchemes(CefRefPtr registrar, std::vector& cookiable_schemes) { registrar->AddCustomScheme("test", true, false, false);//註冊一個新的協議test } //初始化時調用 void InitTest() { CefRegisterSchemeHandlerFactory("test", "test", new ClientSchemeHandlerFactory());//註冊一個新的域名,並且新建一個可以處理此域名請求的類 } } // namespace scheme_test 4.兩個關鍵的類 class CWebClient : public CefClient , public CefLifeSpanHandler , public CefRequestHandler { public: CMyWebBrowser m_wndBrowser; public: CWebClient(void){} virtual ~CWebClient(void){} virtual CefRefPtr GetLifeSpanHandler() { return this; } virtual CefRefPtr GetRequestHandler() { return this; } //virtual bool DoClose( CefRefPtr browser ); //virtual void OnBeforeClose( CefRefPtr browser ); virtual void OnAfterCreated( CefRefPtr browser ); //此處處理接收到的message virtual bool OnProcessMessageReceived( CefRefPtr browser, CefProcessId source_process, CefRefPtr message ); //此處加載本地html資源 virtual CefRefPtr GetResourceHandler( CefRefPtr browser, CefRefPtr frame, CefRefPtr request ); private: bool ParseTestUrl(const std::string& url, std::string* file_name, std::string* mime_type); public: IMPLEMENT_REFCOUNTING(CWebClient); IMPLEMENT_LOCKING(CWebClient); }; class ClientApp: public CefApp ,public CefBrowserProcessHandler ,public CefRenderProcessHandler { public: ClientApp(void); ClientApp(HWND hWnd); ~ClientApp(void); virtual CefRefPtr GetBrowserProcessHandler() OVERRIDE { return this; } virtual CefRefPtr GetRenderProcessHandler()OVERRIDE { return this; } //此處處理js和c++調用 virtual void OnContextCreated( CefRefPtr browser, CefRefPtr frame, CefRefPtr context ); virtual void OnContextInitialized() OVERRIDE; //此處要註冊一個新的協議test virtual void OnRegisterCustomSchemes( CefRefPtr registrar ); BOOL CreateBrowser(HWND hWnd, CRect rect, LPCTSTR pszURL); public: CefRefPtr m_cefHandler; private: IMPLEMENT_REFCOUNTING(ClientApp); }; 5.c++和js相互調用 第一種: class CefV8ExtensionHandler : public CefV8Handler { public: CefV8ExtensionHandler(){} ~CefV8ExtensionHandler(){} virtual bool Execute( const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception ); IMPLEMENT_REFCOUNTING(CefV8ExtensionHandler); }; void ClientApp::OnContextCreated( CefRefPtr browser, CefRefPtr frame, CefRefPtr context ) { CefRefPtr obj = context->GetGlobal(); CefRefPtr handler = new CefV8ExtensionHandler(); obj->SetValue("test", CefV8Value::CreateFunction("test", handler), V8_PROPERTY_ATTRIBUTE_READONLY); } bool CefV8ExtensionHandler::Execute( const CefString& name, CefRefPtr object, const CefV8ValueList& arguments, CefRefPtr& retval, CefString& exception ) { if (name == "test") { std::string arg1 = arguments[0]->GetStringValue(); //MessageBoxA(NULL, arg1.c_str(), NULL, NULL); retval = CefV8Value::CreateString(arg1); CefRefPtr browser = CefV8Context::GetCurrentContext()->GetBrowser(); ASSERT(browser.get()); CefRefPtr message = CefProcessMessage::Create("test"); browser->SendProcessMessage(PID_BROWSER, message); return true; } return false; } 第二種: std::string app_code = "var app;" "if (!app)" " app = {};" "(function() {" " app.sendMessage = function(name, arguments) {" " native function sendMessage();" " return sendMessage(name, arguments);" " };" " app.setMessageCallback = function(name, callback) {" " native function setMessageCallback();" " return setMessageCallback(name, callback);" " };" " app.removeMessageCallback = function(name) {" " native function removeMessageCallback();" " return removeMessageCallback(name);" " };" "})();"; CefRegisterExtension("v8/app", app_code, new ClientAppExtensionHandler(this)); 6.自定義標題欄需要子類化瀏覽器窗口方能接收到消息 class CMyWebBrowser : public CWnd { DECLARE_DYNCREATE(CMyWebBrowser) public: CMyWebBrowser(void); virtual ~CMyWebBrowser(void); protected: DECLARE_MESSAGE_MAP() public: afx_msg LRESULT OnNcHitTest(CPoint point); }; LRESULT CMyWebBrowser::OnNcHitTest(CPoint point) { CRect rc; GetClientRect(&rc); rc.top = rc.top; rc.left = rc.left; rc.right = rc.right; rc.bottom = 20; ClientToScreen(&rc); CPoint screenpoint(point); ScreenToClient(&screenpoint); if (rc.PtInRect(point)) { AfxGetApp()->GetMainWnd()->PostMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(screenpoint.x, screenpoint.y)); return 0; } else return CWnd::OnNcHitTest(point); } void CWebClient::OnAfterCreated( CefRefPtr browser ) { HWND hWnd = browser->GetHost()->GetWindowHandle(); HWND hChildWnd = ::GetNextWindow(hWnd, GW_CHILD ); m_wndBrowser.SubclassWindow(hChildWnd); CefLifeSpanHandler::OnAfterCreated(browser); } 7.消息循環 int CtestCEFApp::ExitInstance() { if( m_bCEFInitialized ) { m_bCEFInitialized = false; m_cefApp = NULL; CefShutdown(); } return CWinAppEx::ExitInstance(); } BOOL CtestCEFApp::PumpMessage() { if( m_bCEFInitialized ) CefDoMessageLoopWork(); return CWinAppEx::PumpMessage(); } --------------------- 本文來自 lls2012 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/lls2012/article/details/47976101?utm_source=copy