CEF 嵌入到MFC的流程,包括启动CEF以及CEF程序的关闭流程。

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);

这里的m_handler是继承了CefClient以及其他接口类的一个类,用来管理浏览器的行为,例如加载、重新加载、前进、后退等,基本上是围绕这个类做文章。

至此已经创建好了一个浏览器。要丰富浏览器的功能,则需要继承更多的接口类并实现对应的方法。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();

如果这是个顶层窗口,即app的m_pMainWnd,那么执行CDialog::OnClose()之后,会有个群发的 WM_DESTROY,此时CEF会调用OnBeforeClose,指示浏览器马上要关闭了,cefclient中还增加了判断浏览器个数为0,则发送退出消息,指示应用程序可以退出了。

如果承载了浏览器的对话框不是顶层窗口,那么在第二次进入OnClose,即允许窗口关闭的流程时,需要告诉顶层窗口,顶层窗口收到此消息后,再执行顶层窗口的OnClose。


2,在所有浏览器都关闭之后,MFC应用程序就可以退出了,网上的说法是在ExitInstance()里调用CefShutdown(),实践证明在Debug模式下会崩溃,后来我改到在

InitInstance 返回前调用,则不会有问题。





你可能感兴趣的:(CEF 嵌入到MFC的流程,包括启动CEF以及CEF程序的关闭流程。)