cef 集成到qt

qt有自带的浏览器,好像也是谷歌浏览器的内核,但是没有用过不知道性能怎么样.cef需要用Cmake生成VS工程文件,在VS中先编译libcef_dll_wrapper,大概是生成cef的适配器,然后生成cefsimple,到这个工程下的Debug目录找到cefsimple.exe,运行成功,我的另外一篇例子有详细的过程.

cef集成到qt

下载msvc版本的qt,这个版本的可以使用vs的编译器,比如

qt-opensource-windows-x86-msvc2015_64-5.7.1.exe

下载地址

http://download.qt.io/archive/qt/5.7/5.7.1/

qt另外有MinGW版本的,这个可能不能集成cef

接下家重新编译libcef_dll_wrapper,更改运行库的线程方式.

项目——属性——配置属性——C/C++——代码生成:他有/MT,/MTd,/Md,/MDd四个选项,你必须让所有使用的库都使用相同的配置,否则就会有相应的提示,甚至可能会出现无法解析的函数。有时我们使用的库不是自己可以控制的,那么就只能把工程属性设置成河你使用的库相同的选项。

参考 https://blog.csdn.net/pgmsoul/article/details/4203941

把这个选项选改为 MD ,然后重新编译libcef_dll_wrapper.   往qt移植需要改一下,在vs里不用了

参考 https://blog.csdn.net/fanhenghui/article/details/79781130

然后新建Qt工程,或者导入我的qt工程.

https://pan.baidu.com/s/1ZPjHIH0Mv29jSJmcMTNv4Q

其实就是有几个文件.

在工程目录下新建cef文件夹,在新建include和lib文件夹.把cef编译前的include内容复制到cef/include文件夹内.

把libcef_dll_wrapper用MD方式编译后的libcef_dll_wrapper.dll和cef源码/Debug/libcef.lib,两个文件放在cef/lib下

我把他贴出来

JDzBrowser.pro

#-------------------------------------------------
#
# Project created by QtCreator 2018-11-13T09:18:32
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = JDzBrowser
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += main.cpp\
    simple_app.cc \
    simple_handler.cc \
    widget.cpp

HEADERS  += simple_app.h \
    simple_handler.h \
    widget.h

FORMS    += widget.ui

INCLUDEPATH+=$$PWD/cef/

LIBS += shell32.lib \
$$PWD/cef/lib/libcef.lib \
$$PWD/cef/lib/libcef_dll_wrapper.lib \
kernel32.lib \
user32.lib \
ole32.lib \
oleaut32.lib \
gdi32.lib

RC_FILE += icon.rc

simple_app.h

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_
#define CEF_TESTS_CEFSIMPLE_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;
  void OnBeforeCommandLineProcessing(const CefString & process_type, CefRefPtr<CefCommandLine> command_line);
 private:
  // Include the default reference counting implementation.
  IMPLEMENT_REFCOUNTING(SimpleApp);
};

#endif  // CEF_TESTS_CEFSIMPLE_SIMPLE_APP_H_

simple_app.cc

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "simple_app.h"

#include <string>

#include "simple_handler.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/wrapper/cef_helpers.h"

SimpleApp::SimpleApp() {
}

void SimpleApp::OnContextInitialized() {
  CEF_REQUIRE_UI_THREAD();

}
void SimpleApp::OnBeforeCommandLineProcessing(const CefString & process_type, CefRefPtr<CefCommandLine> command_line)
{
    //加载flash插件
    command_line->AppendSwitchWithValue("--ppapi-flash-path", "ppflash/18_0_0_209/pepflashplayer32_18_0_0_209.dll");
    //manifest.json中的version
    command_line->AppendSwitchWithValue("--ppapi-flash-version", "18.0.0.209");
    command_line->AppendSwitch("--disable-extensions");
}

simple_handler.h

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#ifndef CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_
#define CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_

#include "include/cef_client.h"
#include <list>
// List of existing browser windows. Only accessed on the CEF UI thread.
typedef std::list<CefRefPtr<CefBrowser> > BrowserList;
class Widget;
class SimpleHandler : public CefClient,
                      public CefDisplayHandler,
                      public CefLifeSpanHandler,
                      public CefLoadHandler {
 public:
  SimpleHandler(Widget* widget);
  ~SimpleHandler();

  // Provide access to the single global instance of this object.
  static SimpleHandler* GetInstance();

  // CefClient methods:
  virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
    return this;
  }
  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_; }
  BrowserList GetBrowserList(){return browser_list_;}
 private:
  BrowserList browser_list_;
  Widget* widget;

  bool is_closing_;

  // Include the default reference counting implementation.
  IMPLEMENT_REFCOUNTING(SimpleHandler);
};

#endif  // CEF_TESTS_CEFSIMPLE_SIMPLE_HANDLER_H_

simple_handler.cc

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "simple_handler.h"

#include <sstream>
#include <string>

#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
#include "widget.h"
namespace {

SimpleHandler* g_instance = NULL;

}  // namespace

SimpleHandler::SimpleHandler(Widget* w)
    : is_closing_(false) {
  DCHECK(!g_instance);
  g_instance = this;
  this->widget=w;
}

SimpleHandler::~SimpleHandler() {
  g_instance = NULL;
}

// 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);
  int nID = browser->GetIdentifier();
  widget->browserId=nID;
}

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.
  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->LoadString(ss.str(), failedUrl);
}

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

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "simple_handler.h"
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    int browserId;
private:
    Ui::Widget *ui;
    CefRefPtr<SimpleHandler> m_browserEvent;
    CefRefPtr<CefBrowser> GetBrowserByID(int nWebBrowserID);
public slots:
    void onUrl();

};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDesktopWidget>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    HWND wnd = (HWND)ui->widget->winId();

    CefWindowInfo cefWndInfo;
    QString strUrl = "https://www.baidu.com";
    //QString strUrl = "chrome://version";

    RECT winRect;

    QDesktopWidget* pDeskTop = QApplication::desktop();
    QRect qtRect = pDeskTop->screenGeometry();
    winRect.left = qtRect.left();
    winRect.top = qtRect.top();
    winRect.right = qtRect.right();
    winRect.bottom = qtRect.bottom();

    cefWndInfo.SetAsChild(wnd, winRect);  //将cef界面嵌入qt界面中

    CefBrowserSettings cefBrowSetting;
    m_browserEvent = CefRefPtr<SimpleHandler>(new SimpleHandler(this));
    bool browser = CefBrowserHost::CreateBrowser(cefWndInfo, m_browserEvent, strUrl.toStdString(), cefBrowSetting, NULL);
    connect(ui->goButton, SIGNAL(clicked()), this, SLOT(onUrl()));
    showMaximized();
}

Widget::~Widget()
{
    delete ui;
}
CefRefPtr<CefBrowser> Widget::GetBrowserByID(int nWebBrowserID)
{

    for (auto it = m_browserEvent->GetBrowserList().begin(); it != m_browserEvent->GetBrowserList().end(); it++)
    {

        if (nWebBrowserID == it->get()->GetIdentifier())
        {
            return it->get();
        }
    }

    return nullptr;
}
void Widget::onUrl()
{
    CefRefPtr<CefBrowser> pBrower = GetBrowserByID(browserId);
    if (pBrower)
    {
        pBrower->GetMainFrame()->LoadURL(ui->lineEdit->text().toStdString());
    }
}

main.cpp

#include "widget.h"
#include <QApplication>
#include "simple_app.h"
#include "simple_handler.h"

void QCefInitSettings(CefSettings & settings)
{
   // qDebug()<<"QCefInitSettings";

    //std::string cache_path = AppGetWorkingDirectory().toStdString() + "/.cache";//缓存地址
   // CefString(&settings.cache_path) = CefString(cache_path);
    settings.multi_threaded_message_loop = true;//多线程消息循环
    settings.log_severity = LOGSEVERITY_DISABLE;//日志

    settings.no_sandbox = true;//沙盒
}



int QCefInit(int& argc, char** argv)
{
   //  qDebug()<<"QCefInit";
    HINSTANCE hInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));

    CefMainArgs mainArgs(hInstance);
    //CefRefPtr<SimpleApp> app(new SimpleApp);
    CefRefPtr<SimpleApp> app(new SimpleApp); //CefApp实现,用于处理进程相关的回调。

    int exit_code = CefExecuteProcess(mainArgs, app.get(), nullptr);
    if (exit_code >= 0) {
        return exit_code;
    }

    CefSettings settings;
    QCefInitSettings(settings);

    CefInitialize(mainArgs, settings, app, nullptr);

    //m_handler = new QCefClientHandler();

    return -1;
}
void CefQuit()
{
    CefShutdown();
}
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    int result = QCefInit(argc, argv);
    if (result >= 0) {
        return result;
    }
    Widget w;
    w.show();
    a.exec();

    CefQuit();

    return 0;
}

widget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>400</width>
    <height>300</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>cef qt test</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout">
   <property name="spacing">
    <number>0</number>
   </property>
   <property name="leftMargin">
    <number>0</number>
   </property>
   <property name="topMargin">
    <number>0</number>
   </property>
   <property name="rightMargin">
    <number>0</number>
   </property>
   <property name="bottomMargin">
    <number>0</number>
   </property>
   <item>
    <widget class="QWidget" name="toolbar" native="true">
     <property name="minimumSize">
      <size>
       <width>0</width>
       <height>40</height>
      </size>
     </property>
     <property name="maximumSize">
      <size>
       <width>16777215</width>
       <height>40</height>
      </size>
     </property>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <property name="spacing">
       <number>0</number>
      </property>
      <property name="leftMargin">
       <number>0</number>
      </property>
      <property name="topMargin">
       <number>0</number>
      </property>
      <property name="rightMargin">
       <number>0</number>
      </property>
      <property name="bottomMargin">
       <number>0</number>
      </property>
      <item>
       <widget class="QLineEdit" name="lineEdit">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>40</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>16777215</width>
          <height>40</height>
         </size>
        </property>
        <property name="styleSheet">
         <string notr="true">font-size:15px;</string>
        </property>
        <property name="text">
         <string>http://www.qq.com</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="goButton">
        <property name="minimumSize">
         <size>
          <width>0</width>
          <height>40</height>
         </size>
        </property>
        <property name="maximumSize">
         <size>
          <width>16777215</width>
          <height>40</height>
         </size>
        </property>
        <property name="text">
         <string>访问</string>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item>
    <widget class="QWidget" name="widget" native="true"/>
   </item>
  </layout>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

然后在qt中构建项目

得到这样的构建目录.

 

其中的.exe就是我们的主程序

我们还需要将qt的运行时库,dll,复制到主程序目录.

在qt安装目录搜索这几个dll.

复制到主程序目录下.

在再cefsimple下,把除了cefsimple.exe,和后缀是exp,ilk,pdb,其他的文件都复制到主程序相同目录

运行JDzBrowser.exe

我的编译结果

https://pan.baidu.com/s/16bRDZ6wW_lqbZBcZ0frCHg

  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
CEF(Chromium Embedded Framework)是一个基于Chromium的开源框架,主要用于嵌入式浏览器应用程序的开发。Qt是一个跨平台的C++应用程序开发框架,提供了许多GUI和多媒体功能。在以下步骤中,我们将介绍如何将CEFQt集成。 1. 下载CEF 首先,需要从CEF官网(https://cefsharp.github.io/)下载适合您操作系统的CEF版本。您可以选择标准版本或使用NuGet包。 2. 创建Qt项目 使用Qt Creator创建一个新的Qt项目。在项目设置中,确保您已选择正确的构建工具链和平台。在.pro文件中添加以下内容: ``` LIBS += -L/path/to/cef -lcef INCLUDEPATH += /path/to/cef ``` 其中,`/path/to/cef`是CEF的安装路径。 3. 集成CEFQt项目中,您可以使用CEF的C API或C++ API。在本例中,我们将使用C++ API。 首先,将CEF的C++头文件添加到Qt项目中。在您的Qt项目中创建一个新的C++源文件,并使用以下代码初始化CEF: ``` #include "include/cef_app.h" #include "include/cef_browser.h" #include "include/cef_client.h" class CefApplication : public CefApp, public CefBrowserProcessHandler { public: // Implement CefApp methods here }; CefRefPtr<CefApplication> app(new CefApplication); CefMainArgs mainArgs(argc, argv); CefInitialize(mainArgs, app, NULL); ``` 这将初始化CEF并创建一个CEF应用程序。 接下来,您需要创建一个CEF客户端类。客户端类处理浏览器事件和渲染进程事件。以下是一个简单的CEF客户端类: ``` class CefClientImpl : public CefClient, public CefLifeSpanHandler { public: // Implement CefClient and CefLifeSpanHandler methods here }; CefRefPtr<CefClientImpl> client(new CefClientImpl); ``` 最后,将CEF嵌入到Qt应用程序中。在Qt应用程序的主窗口中,将CEF嵌入到QWidget中: ``` CefWindowInfo windowInfo; windowInfo.SetAsChild(reinterpret_cast<cef_window_handle_t>(widget->winId()), CefRect(0, 0, width, height)); CefBrowserSettings browserSettings; CefBrowserHost::CreateBrowserSync(windowInfo, client.get(), "http://www.google.com", browserSettings, NULL); ``` 这将在Qt应用程序的QWidget中创建一个CEF浏览器。 4. 运行应用程序 现在,您可以运行Qt应用程序并查看CEF浏览器。使用Qt的GUI控件可以与CEF浏览器进行交互,例如在Qt窗口中显示CEF浏览器的网页内容,或在CEF浏览器中嵌入Qt控件。 注意:在集成CEF时,需要考虑QtCEF的线程模型。Qt使用主线程作为GUI线程,而CEF使用多个线程处理浏览器事件和渲染进程事件。因此,在使用CEF时,需要确保在正确的线程上执行GUI操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值