CEF嵌入到MFC的例子很多,网上也很容易可以找到,我用的CEF版本是cef_binary_3.2171.1979_windows32,开发环境是VS2008。
大致流程是:
1,在应用程序InitInstance()中,初始化CEF:
void* sandbox_info = NULL;
CefMainArgs main_args(theApp.m_hInstance);
CefRefPtr app(new ClientApp);
int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
if (exit_code >= 0) {
// The sub-process has completed so return here.
return exit_code;
}
CefSettings settings;
//CefSettingsTraits::init(&settings);
settings.single_process = true;
settings.no_sandbox = true;
settings.multi_threaded_message_loop=true;
CefInitialize(main_args, settings, app.get(), sandbox_info);
2,创建浏览器。
在要创建浏览器的窗口里,创建浏览器,例如在一个对话框里OnInitDialog()函数里:
CRect rt;
GetClientRect(&rt);
CefWindowInfo window_info;
window_info.SetAsChild(this->GetSafeHwnd(), rt);
m_handler = new ClientHandler();
m_handler->SetMainWindowHandle(m_hWnd);
CefBrowserSettings browser_settings;
std::string url;
url = "www.baidu.com";
CefBrowserHost::CreateBrowser(window_info, m_handler.get(), url, browser_settings, NULL);
至此已经创建好了一个浏览器。要丰富浏览器的功能,则需要继承更多的接口类并实现对应的方法。cefclient方法已经实现了较多的接口,可以参考。
主要讲下关闭CEF程序的流程。
之前在网上看到的都说在应用程序的ExitInstance()中调用CefShutdown(),实践了一下发现在退出时会崩溃。在网上看了一些资料,其中
https://github.com/fanfeilong/cefutil/blob/master/doc/CEF_Close.md
这里说的比较好,我也是参照这个来说以下的关闭流程。
1,在退出应用程序前,一般是窗口收到WM_CLOSE消息的响应函数OnClose中,需要调用browser->GetHost()->CloseBrowser(false);来关闭一个浏览器,也有关闭所有浏览器的方法(见cefclient例子里的ClientHandler::CloseAllBrowsers),调用了CloseBrowser后,CEF会调用DoClose,然后会再发一个WM_CLOSE给窗口,此时继续进入到OnClose中,这时就可以关闭窗口了,因此OnClose的实现大概是这样的:
if (m_handler.get() && !m_handler->IsClosing()) {
CefRefPtr browser = m_handler->GetBrowser();
if (browser.get()) {
// Notify the browser window that we would like to close it. This
// will result in a call to ClientHandler::DoClose() if the
// JavaScript 'onbeforeunload' event handler allows it.
browser->GetHost()->CloseBrowser(false);
// Cancel the close.
return ;
}
}
// Allow the close
CDialog::OnClose();
如果承载了浏览器的对话框不是顶层窗口,那么在第二次进入OnClose,即允许窗口关闭的流程时,需要告诉顶层窗口,顶层窗口收到此消息后,再执行顶层窗口的OnClose。
2,在所有浏览器都关闭之后,MFC应用程序就可以退出了,网上的说法是在ExitInstance()里调用CefShutdown(),实践证明在Debug模式下会崩溃,后来我改到在
InitInstance 返回前调用,则不会有问题。