赞助

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_OBJECT

public:
    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();
}

 

posted @ 2025-08-03 18:54  车臣  阅读(106)  评论(0)    收藏  举报