在上一篇 Qt实现 CEF制作浏览器(首篇) 中,编译了cefsimple,打开了浏览器,不过该浏览器是demo做例子用的,但是我们的目的是为了嵌入qt窗口中。
本篇将介绍如何将CEF生成的浏览器嵌入到qt中窗口使用。
认为大家有一定基础,所以不再介绍如何在vs中加载licef_dll_wrapper等库和cef头文件等。
目录
一、准备步骤
1、编译licef_dll_wrapper库,记得如下把运行库改为多线程DLL(MD),debug下改为MDd。
2、把simple_handler.cc和simple_handler.h拷贝到自己的项目src里,直接使用
3、注释掉以下不需要的函数。
4、找到wWinMain,这是cef初始化的相关代码,拷贝到自己的cef初始化代码中。
二、运行效果
三、主要代码
1、main函数
int main(int argc, char *argv[])
{
//初始化cef
bool flag = CefManager::instance()->CefInit();
if (!flag) {
return -1;
}
QApplication a(argc, argv);
QtCef w;
w.show();
int ret = a.exec();
CefManager::instance()->CefQuit();
return ret;
}
对CEF的初始化和退出放在了一个全局静态类中,比较方便去维护和复用,初始化为什么放在main函数之前?因为在我的软件,如果放在其他地方,会出现两个运行程序,目前原因还不清楚。
2、cef初始化代码
bool CefManager::CefInit()
{
HINSTANCE hInstance = ::GetModuleHandle(NULL);
// Enable High-DPI support on Windows 7 or newer.
CefEnableHighDPISupport();
void* sandbox_info = NULL;
#if defined(CEF_USE_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
// Provide CEF with command-line arguments.
CefMainArgs main_args(hInstance);
// CEF applications have multiple sub-processes (render, plugin, GPU, etc)
// that share the same executable. This function checks the command-line and,
// if this is a sub-process, executes the appropriate logic.
int exit_code = CefExecuteProcess(main_args, NULL, sandbox_info);
if (exit_code >= 0) {
// The sub-process has completed so return here.
return exit_code;
}
// Specify CEF global settings here.
CefSettings settings;
#if !defined(CEF_USE_SANDBOX)
settings.no_sandbox = true;
#endif
settings.multi_threaded_message_loop = true;
// SimpleApp implements application-level callbacks for the browser process.
// It will create the first browser instance in OnContextInitialized() after
// CEF has initialized.
CefRefPtr<SimpleApp> app(new SimpleApp);
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), sandbox_info);
return true;
}
3、浏览器创建
bool QCefView::createCefBrowser()
{
RECT rect;
rect.left = 0;
rect.top = 0;
rect.right = qobject_cast<QWidget*>(this->parent())->width();
rect.bottom = qobject_cast<QWidget*>(this->parent())->height();
CefWindowInfo windowInfo;
CefBrowserSettings browserSettings;
windowInfo.SetAsChild(reinterpret_cast<HWND>(this->winId()), rect);
CefBrowserHost::CreateBrowser(windowInfo, _browserHandler.get(),
CefString(_url.toStdWString()), browserSettings, nullptr);
qDebug() << "CreateBrowser success!" << _url;
return true;
}
通过CreteBrowser()函数创建浏览器,CefWindowInfo对象的SetAsChild函数设置当前窗口的句柄ID为接下来浏览器的父窗口,从而实现内嵌CEF浏览器到Qt窗口中。
4、加载Url
void QCefView::loadUrl(const QString &url)
{
if (url.isEmpty()) return;
_url = url;
qDebug() << "loadUrl" << _url;
createCefBrowser();
}
这里直接传入QString字符串,然后调用创建浏览器的接口。
5、界面内嵌cef的父窗口
QtCef::QtCef(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
qDebug() << "QtCef Init";
QVBoxLayout * vlayout = new QVBoxLayout;
vlayout->setSpacing(0);
vlayout->setMargin(0);
_cefView = new QCefView(this);
vlayout->addWidget(_cefView);
this->setLayout(vlayout);
_cefView->loadUrl("http://www.baidu.com");
}
通过addwidget将搭载cef浏览器的qt窗口添加到我们需要显示的界面上。
四、完整代码和库:
这只是一个简单的演示demo,功能并不完善,大家可以自行在此基础上进行拓展和完善。
如果有需要功能完善的代码和库的同学可以关注我的微信公众号 回复 CEF浏览器 领取源码: