MFC嵌入浏览器框架CEF
flyfish
环境 win7,VC2013 update5
Message Loop Integration
CEF can also integrate with an existing application message loop instead of running its own message loop. There are two ways to do this.
Call CefDoMessageLoopWork() on a regular basis instead of calling CefRunMessageLoop(). Each call to CefDoMessageLoopWork() will perform a single iteration of the CEF message loop. Caution should be used with this approach. Calling the method too infrequently will starve the CEF message loop and negatively impact browser performance. Calling the method too frequently will negatively impact CPU usage.
Set CefSettings.multi_threaded_message_loop = true (Windows only). This will cause CEF to run the browser UI thread on a separate thread from the main application thread. With this approach neither CefDoMessageLoopWork() nor CefRunMessageLoop() need to be called. CefInitialize() and CefShutdown() should still be called on the main application thread. You will need to provide your own mechanism for communicating with the main application thread (see for example the message window usage in cefclient_win.cpp). You can test this mode in cefclient on Windows by running with the “–multi-threaded-message-loop” command-line flag.
消息循环整合
CEF能整合现有的应用程序的消息循环替代自己的消息循环 有两种做法
1定期调用CefDoMessageLoopWork() 替代调用CefRunMessageLoop()
每次调用CefDoMessageLoopWork() 将会执行一次CEF消息循环的迭代,小心使用这种方法。调用这个方法频率太少,将会饿死CEF消息循环并且消极的影响浏览器的性能。调用这种方法太频繁将会消极的影响CPU的使用
2 设置CefSettings.multi_threaded_message_loop = true(仅限windows下使用),这将导致CEF运行在浏览器UI线程,该UI线程是从主应用程序分离出来的线程。这种方法既不需要调用CefDoMessageLoopWork() 也不需要调用 CefRunMessageLoop() 。 CefInitialize() 和CefShutdown()这两个函数仍然需要在主应用程序调用。你需要提供你自己的机制和主应用程序线程交流。在cefclient_win.cpp查看消息的使用示例.你可以在windows下使用命令行 “–multi-threaded-message-loop”测试cefclient模式。
APP头文件
BOOL m_bCEFInitialized;//是否初始化
CefRefPtr<ClientApp> m_cefApp;
APP实现文件
APP构造函数
CXApp::CXApp()
{
m_bCEFInitialized = FALSE;
}
APP初始化函数
BOOL CXApp::InitInstance()
{
m_cefApp = new ClientApp();
// get arguments
CefMainArgs main_args(GetModuleHandle(NULL));
// Execute the secondary process, if any.
int exit_code = CefExecuteProcess(main_args, m_cefApp.get(), NULL);
if (exit_code >= 0)
return exit_code;
CefSettings settings;
settings.no_sandbox = TRUE;
//CefString(&settings.cache_path) = szCEFCache;
void* sandbox_info = NULL;
#if CEF_ENABLE_SANDBOX
// Manage the life span of the sandbox information object. This is necessary
// for sandbox support on Windows. See cef_sandbox_win.h for complete details.
CefScopedSandboxInfo scoped_sandbox;
sandbox_info = scoped_sandbox.sandbox_info();
#endif
//CEF Initiaized
m_bCEFInitialized = CefInitialize(main_args, settings, m_cefApp.get(), sandbox_info);
}
退出函数
int CXApp::ExitInstance()
{
// shutdown CEF
if (m_bCEFInitialized)
{
// closing stop work loop
m_bCEFInitialized = FALSE;
// release CEF app
m_cefApp = NULL;
// shutdown CEF
CefShutdown();
}
return CWinApp::ExitInstance();
}
重写函数
BOOL CXApp::PumpMessage()
{
// TODO: 在此添加专用代码和/或调用基类
if (m_bCEFInitialized)
CefDoMessageLoopWork();
return CPUMPKINPWinApp::PumpMessage();
}
对话框初始化函数
BOOL CXDlg::OnInitDialog()
{
CefWindowInfo window_info;
CRect rt;
GetWindowRect(&rt);
window_info.SetAsChild(this->GetSafeHwnd(), rt);
CefRefPtr<ClientHandler> handler(new ClientHandler());
m_cefHandler = handler;
CefBrowserSettings browser_settings;
std::string url;
url = "http://www.baidu.com/";
CefBrowserHost::CreateBrowser(window_info, handler.get(), url, browser_settings, NULL);
}
void CXDlg::OnSize(UINT nType, int cx, int cy)
{
CWnd* cefwindow = FindWindowEx(this->GetSafeHwnd(), NULL, L"CefBrowserWindow", NULL);
if (cefwindow)
{
cefwindow->MoveWindow(0, 0, cx, cy);
}
}
//加载其他网页时调用
CefBrowser* pBrowser = m_cefHandler->m_pBrowser;
CefRefPtr<CefFrame> pMainFram = pBrowser->GetMainFrame();
if (pMainFram)
{
std::string s = "www.baidu.com";
pMainFram->LoadURL(s.c_str());
}