当前位置: 首页 > news >正文

VS2015+ Qt5.9.1 内嵌CEF 环境配置

转载:https://xie.infoq.cn/article/1512f3ac7855295638ca51ee6(Qt下使用CMake编译CEF很关键)

转载:https://blog.csdn.net/qq_41474648/article/details/146129048

转载:https://blog.csdn.net/weixin_45551020/article/details/136383436

工作中没有小事:点石成金,滴水成河,只有认真对待自己所做的一切事情,才能克服万难,取得成功。

一、下载CEF CEF Automated Builds

image

 我下载的是

image

 

二、使用CMake 生产CEF解决方案

image

 不勾选画红色方框的

点击下方Generate 生成解决方案

image

 

三、编译libcef_dll_wrapper.lib

Qt 中常使用的是动态链接(即 MDd),所以需要使用 MDd 的方式重新编译 libcef_dll_wrapper.lib。
右键项目 libcef_dll_wrapper->属性->C/C++->代码生成->运行库:

改为“多线程调试 DLL (/MDd)”(如果是 release 版,则改为“多线程 DLL (/MD)”)

然后重新生成就可以了

image

注意: Qt Creator 创建的嵌入 cef 功能的项目,debug 运行加载的页面是空白的(有问题),所以只能创建 release 版本。

 三、vs新建QtCEF的demo

  1. 我们先需要复制cef目录下(前面编译的cef目录)Include到demo下的目录里面
  2. lib目录下存放CEF程序编译时依赖的静态链接库(.lib文件)。主要有libcef.lib和libcef_dll_wrapper.lib,注意区分debug和release版本
  3. 链接器-》常规-》附加库目录 $(SolutionDir)\lib\Release
  4. 链接器-》常规-》输入:(注意区分debug和release)libcef.lib libcef_dll_wrapper.lib
  5. exe同级目录下的文件(注意区分debug和release 

    image

     

main.cpp

include "QtCEF.h"
#include <QtWidgets/QApplication>
#include "simple_app.h"/**
* 初始化QT以及CEF相关
*/
int init_qt_cef(int& argc, char** argv)
{const HINSTANCE h_instance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));const CefMainArgs main_args(h_instance);const CefRefPtr<SimpleApp> app(new SimpleApp); //CefApp实现,用于处理进程相关的回调。const int exit_code = CefExecuteProcess(main_args, app.get(), nullptr);if (exit_code >= 0){return exit_code;}// 设置配置
    CefSettings settings;settings.multi_threaded_message_loop = true; //多线程消息循环settings.log_severity = LOGSEVERITY_DISABLE; //日志settings.no_sandbox = true; //沙盒
CefInitialize(main_args, settings, app, nullptr);return -1;
}int main(int argc, char *argv[])
{QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 解决高DPI下,界面比例问题
QApplication a(argc, argv);const int result = init_qt_cef(argc, argv);if (result >= 0){return result;}QtCEF w;w.show();int ret = a.exec();CefShutdown(); // 关闭CEF,释放资源return ret;
}

QtCEF.h

#include <QtWidgets/QMainWindow>
#include "ui_QtCEF.h"
#include "simple_handler.h"class QtCEF : public QMainWindow
{Q_OBJECTpublic:QtCEF(QWidget *parent = Q_NULLPTR);private:Ui::QtCEFClass ui;private:CefRefPtr<SimpleHandler> m_handler;
};

QtCEF.cpp

#include "QtCEF.h"
#include "include/cef_request_context.h"QtCEF::QtCEF(QWidget *parent): QMainWindow(parent), m_handler(new SimpleHandler())
{ui.setupUi(this);CefWindowInfo cef_wnd_info;QString str_url = "https://www.baidu.com/";RECT win_rect;QRect rect = this->geometry();win_rect.left = rect.left();win_rect.right = rect.right();win_rect.top = rect.top();win_rect.bottom = rect.bottom();cef_wnd_info.SetAsChild((HWND)this->winId(), win_rect); //将cef界面嵌入qt界面中
    CefBrowserSettings cef_browser_settings;CefBrowserHost::CreateBrowser(cef_wnd_info,m_handler,str_url.toStdString(),cef_browser_settings,nullptr, CefRequestContext::GetGlobalContext());
}

simple_handler.h

#include "include/cef_client.h"#include <list>class SimpleHandler : public CefClient,public CefLifeSpanHandler,public CefLoadHandler
{
public:explicit SimpleHandler();~SimpleHandler();// Provide access to the single global instance of this object.static SimpleHandler* GetInstance();virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE{return this;}virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE { return this; }// CefLifeSpanHandler methods:virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;// CefLoadHandler methods:virtual void OnLoadError(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,ErrorCode errorCode,const CefString& errorText,const CefString& failedUrl) OVERRIDE;// Request that all existing browser windows close.void CloseAllBrowsers(bool force_close);bool IsClosing() const { return is_closing_; }private:// List of existing browser windows. Only accessed on the CEF UI thread.typedef std::list<CefRefPtr<CefBrowser>> BrowserList;BrowserList browser_list_;bool is_closing_;// Include the default reference counting implementation.
    IMPLEMENT_REFCOUNTING(SimpleHandler);
};

simple_handler.cpp

#include "simple_handler.h"#include <sstream>
#include <string>#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/cef_parser.h"
#include "include/views/cef_browser_view.h"
#include "include/views/cef_window.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"namespace
{SimpleHandler* g_instance = nullptr;// Returns a data: URI with the specified contents.std::string GetDataURI(const std::string& data, const std::string& mime_type){return "data:" + mime_type + ";base64," +CefURIEncode(CefBase64Encode(data.data(), data.size()), false).ToString();}
} // namespace

SimpleHandler::SimpleHandler() : is_closing_(false)
{DCHECK(!g_instance);g_instance = this;
}SimpleHandler::~SimpleHandler()
{g_instance = nullptr;
}// static
SimpleHandler* SimpleHandler::GetInstance()
{return g_instance;
}void SimpleHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();// Add to the list of existing browsers.
    browser_list_.push_back(browser);
}bool SimpleHandler::DoClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();// Closing the main window requires special handling. See the DoClose()// documentation in the CEF header for a detailed destription of this// process.if (browser_list_.size() == 1){// Set a flag to indicate that the window close should be allowed.is_closing_ = true;}// Allow the close. For windowed browsers this will result in the OS close// event being sent.return false;
}void SimpleHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
{CEF_REQUIRE_UI_THREAD();// Remove from the list of existing browsers.BrowserList::iterator bit = browser_list_.begin();for (; bit != browser_list_.end(); ++bit){if ((*bit)->IsSame(browser)){browser_list_.erase(bit);break;}}if (browser_list_.empty()){// All browser windows have closed. Quit the application message loop.
        CefQuitMessageLoop();}
}void SimpleHandler::OnLoadError(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,ErrorCode errorCode,const CefString& errorText,const CefString& failedUrl)
{CEF_REQUIRE_UI_THREAD();// Don't display an error for downloaded files.if (errorCode == ERR_ABORTED)return;// Display a load error message using a data: URI.
    std::stringstream ss;ss << "<html><body bgcolor=\"white\">""<h2>Failed to load URL "<< std::string(failedUrl) << " with error " << std::string(errorText)<< " (" << errorCode << ").</h2></body></html>";frame->LoadURL(GetDataURI(ss.str(), "text/html"));
}void SimpleHandler::CloseAllBrowsers(bool force_close)
{if (!CefCurrentlyOn(TID_UI)){// Execute on the UI thread.CefPostTask(TID_UI, base::Bind(&SimpleHandler::CloseAllBrowsers, this,force_close));return;}if (browser_list_.empty())return;BrowserList::const_iterator it = browser_list_.begin();for (; it != browser_list_.end(); ++it)(*it)->GetHost()->CloseBrowser(force_close);
}

simple_app.h

#include "include/cef_app.h"// Implement application-level callbacks for the browser process.
class SimpleApp : public CefApp, public CefBrowserProcessHandler
{
public:SimpleApp();// CefApp methods:virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()OVERRIDE{return this;}// CefBrowserProcessHandler methods:virtual void OnContextInitialized() OVERRIDE;private:// Include the default reference counting implementation.
    IMPLEMENT_REFCOUNTING(SimpleApp);
};

simple_app.cpp

#include "simple_app.h"#include <string>
#include "include/views/cef_window.h"
#include "include/wrapper/cef_helpers.h"
#include "simple_handler.h"SimpleApp::SimpleApp()
{
}void SimpleApp::OnContextInitialized()
{CEF_REQUIRE_UI_THREAD();
}

 

http://www.sczhlp.com/news/4734/

相关文章:

  • Atom编辑器离线中文设置
  • 2025牛客暑期多校训练营5 K.Perfect Journey
  • 8月3日总结
  • 通过自定义聚合增强 Kubernetes Event 管理
  • 2025 -- 云智计划 -- 【CSP-S】模拟赛 #910_总结+题解
  • 详细介绍:设计模式:访问者模式 Visitor
  • Misaka2298的OI零碎知识点 / Trick
  • 原地变配与快照变配
  • Misaka2298的OI错误集
  • 【Tryhackme】Soupedecode 01 域控渗透
  • 计算PE和PB历史分位的尝试(失败)
  • 软考系统分析师每日学习卡 | [日期:2025-08-03] | [今日主题:段页式存储]
  • Buildroot挂载网络内核和根文件系统
  • 8.3总结
  • 8月3号
  • 云原生环境中的镜像兼容性(NFD项目)
  • 【自学嵌入式:51单片机】实现DS18B20温度报警器
  • 2025.8.3
  • docker下载安装
  • NOIP0805模拟赛题解
  • Weblogic-CVE-2018-2894
  • plink软件 二分类 logistic GWAS分析中 P值为NA
  • 深度解析Manus:从多智能体架构到通用AI Agent的技术革命 - 实践
  • 基于 PyTorch 动手实现 LLM
  • vanna chat2db db-gpt
  • Docker安装Nacos
  • C++14新特性个人总结
  • CF1709E 题解
  • Spring Data Neo4j 学习
  • 单链表的定义与基本操作