增加对QCefView的支持,已知BUG,无法多线程模式

This commit is contained in:
JackLee 2025-03-19 22:47:04 +08:00
parent 3830c3d47f
commit 02b34502e1
15 changed files with 768 additions and 282 deletions

View File

@ -13,12 +13,12 @@
#pragma once #pragma once
// clang-format off // clang-format off
#define CEF_VERSION "134.3.2+g615db2f+chromium-134.0.6998.89" #define CEF_VERSION "127.3.5+g114ea2a+chromium-127.0.6533.120"
#define CEF_VERSION_MAJOR 134 #define CEF_VERSION_MAJOR 127
#define CEF_VERSION_MINOR 3 #define CEF_VERSION_MINOR 3
#define CEF_VERSION_PATCH 2 #define CEF_VERSION_PATCH 5
#define CEF_COMMIT_NUMBER 3151 #define CEF_COMMIT_NUMBER 3037
#define CEF_COMMIT_HASH "615db2f583e46822d28a4f2a57c3ef7316c5b17d" #define CEF_COMMIT_HASH "114ea2af1ba9da18c4ac5e599ccdbb17d01ba75a"
// clang-format on // clang-format on
#endif // CefVersion #endif // CefVersion

View File

@ -94,7 +94,7 @@ MESSAGE(STATUS "---------- END---------------")
#suicpp #suicpp
FILE(GLOB src_sui "${PROJECT_SOURCE_DIR}/src/*.*") FILE(GLOB src_sui "${PROJECT_SOURCE_DIR}/src/*.*")
FILE(GLOB browser "${PROJECT_SOURCE_DIR}/src/Cef/*.*") FILE(GLOB browser "${PROJECT_SOURCE_DIR}/src/cef/*.*")
SET(PROJECT_SOURCES ${browser} ${src_sui}) SET(PROJECT_SOURCES ${browser} ${src_sui})
# qFatalqDebug # qFatalqDebug

View File

@ -14,7 +14,7 @@
#include <QResizeEvent> #include <QResizeEvent>
#include <QWindow> #include <QWindow>
#include "CefDownloadManager.h" #include "DownloadManager.h"
CefViewWidget::CefViewWidget(const QString url, const QCefSetting* setting, QWidget* parent /* = 0*/) CefViewWidget::CefViewWidget(const QString url, const QCefSetting* setting, QWidget* parent /* = 0*/)
: QCefView(url, setting, parent) : QCefView(url, setting, parent)
@ -74,7 +74,7 @@ CefViewWidget::onNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item, c
{ {
// keep the item into list or map, and call item->start() to allow the download // keep the item into list or map, and call item->start() to allow the download
CefDownloadManager::getInstance().AddNewDownloadItem(item); DownloadManager::getInstance().AddNewDownloadItem(item);
} }
void void
@ -83,7 +83,7 @@ CefViewWidget::onUpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item
// control the download by invoking item->pause(), item->resume(), item->cancel() // control the download by invoking item->pause(), item->resume(), item->cancel()
CefDownloadManager::getInstance().UpdateDownloadItem(item); DownloadManager::getInstance().UpdateDownloadItem(item);
} }
void void

View File

@ -1,5 +1,5 @@
#ifndef CEFVIEWWIDGET_H #ifndef CUSTOMCEFVIEW_H
#define CEFVIEWWIDGET_H #define CUSTOMCEFVIEW_H
#include <QScreen> #include <QScreen>
@ -13,7 +13,7 @@ class CefViewWidget : public QCefView
Q_OBJECT Q_OBJECT
public: public:
CefViewWidget(const QString url, const QCefSetting* setting, QWidget* parent = 0); CefViewWidget(const QString url, const QCefSetting* setting, QWidget* parent = 0);
~CefViewWidget(); ~CefViewWidget();

View File

@ -1,149 +1,30 @@
#include "CefWidget.h" #include "CefWidget.h"
CefWidget::CefWidget(QWidget* parent) CefWidget::CefWidget(QWidget *parent)
: QMainWindow(parent /*, Qt::FramelessWindowHint*/) : QWidget(parent)
{ {
initBrowser(); QWidget* widget = new QWidget();
this->layout()->addWidget(widget);
} }
CefWidget::~CefWidget() CefWidget::~CefWidget()
{ {
} }
void CefWidget::initBrowser()
void CefWidget::WaitCefQuit()
{ {
m_centralWidget = new QWidget(this);
if (m_viewWidget) {
m_viewWidget->deleteLater();
m_viewWidget = nullptr;
}
QCefSetting setting;
setting.setWindowlessFrameRate(1000);
setting.setHardwareAcceleration(false);
// setting.setBackgroundColor(Qt::magenta);
m_viewWidget = new CefViewWidget("https://www.baidu.com/", &setting, this);
// connect the invokeMethod to the slot
// connect(m_viewWidget, &QCefView::invokeMethod, this, &CefWidget::onInvokeMethod);
// // connect the cefQueryRequest to the slot
// connect(m_viewWidget, &QCefView::cefUrlRequest, this, &CefWidget::onQCefUrlRequest);
// connect(m_viewWidget, &QCefView::cefQueryRequest, this, &CefWidget::onQCefQueryRequest);
// connect(m_viewWidget, &QCefView::reportJavascriptResult, this, &CefWidget::onJavascriptResult);
// connect(m_viewWidget, &QCefView::loadStart, this, &CefWidget::onLoadStart);
// connect(m_viewWidget, &QCefView::loadEnd, this, &CefWidget::onLoadEnd);
// connect(m_viewWidget, &QCefView::loadError, this, &CefWidget::onLoadError);
m_centralWidget->layout()->addWidget(m_viewWidget);
setCentralWidget(m_centralWidget);
} }
void
CefWidget::onInvokeMethod(const QCefBrowserId& browserId, void CefWidget::resizeEvent(QResizeEvent *ev)
const QCefFrameId& frameId,
const QString& method,
const QVariantList& arguments)
{ {
// extract the arguments and dispatch the invocation to corresponding handler
if (0 == method.compare("TestMethod")) {
QString title("QCef InvokeMethod Notify");
QString text = QString("================== Current Thread: QT_UI ==================\r\n"
"Frame: %1\r\n"
"Method: %2\r\n"
"Arguments:\r\n")
.arg(frameId)
.arg(method);
for (int i = 0; i < arguments.size(); i++) {
auto jv = QJsonValue::fromVariant(arguments[i]);
// clang-format off
text.append(
QString("%1 Type:%2, Value:%3\r\n")
.arg(i).arg(arguments[i].typeName()).arg(arguments[i].toString())
);
// clang-format on
}
auto jsonValue = QJsonDocument::fromVariant(arguments);
auto jsonString = QString(jsonValue.toJson());
text.append(QString("\r\nArguments List in JSON format:\r\n%1").arg(jsonString));
QMessageBox::information(this->window(), title, text);
} else {
}
} }
void void CefWidget::closeEvent(QCloseEvent* ev)
CefWidget::onQCefUrlRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QString& url)
{ {
QString title("QCef URL Request");
QString text = QString("Current Thread: QT_UI\r\n"
"URL: %1")
.arg(url);
QMessageBox::information(this->window(), title, text);
} }
void
CefWidget::onQCefQueryRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QCefQuery& query)
{
QString title("QCef Query Request");
QString text = QString("Current Thread: QT_UI\r\n"
"Query: %1")
.arg(query.request());
QMessageBox::information(this->window(), title, text);
QString response = query.request().toUpper();
query.setResponseResult(true, response);
m_viewWidget->responseQCefQuery(query);
}
void
CefWidget::onJavascriptResult(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
const QString& context,
const QVariant& result)
{
auto jsonValue = QJsonDocument::fromVariant(result);
auto jsonString = QString(jsonValue.toJson());
QString title("Javascript result notification");
QString text = QString("Context: %1\r\nResult in JSON format:\r\n%2").arg(context).arg(jsonString);
QMessageBox::information(this->window(), title, text);
}
void
CefWidget::onLoadingStateChanged(const QCefBrowserId& browserId, bool isLoading, bool canGoBack, bool canGoForward)
{
qDebug() << "onLoadingStateChanged, browserId:" << browserId << ", isLoading:" << isLoading
<< ", canGoBack:" << canGoBack << ", canGoForward:" << canGoForward;
}
void
CefWidget::onLoadStart(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
bool isMainFrame,
int transitionType)
{
qDebug() << "onLoadStart, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
<< ", transitionType:" << transitionType;
}
void
CefWidget::onLoadEnd(const QCefBrowserId& browserId, const QCefFrameId& frameId, bool isMainFrame, int httpStatusCode)
{
qDebug() << "onLoadEnd, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
<< ", httpStatusCode:" << httpStatusCode;
}
void
CefWidget::onLoadError(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
bool isMainFrame,
int errorCode,
const QString& errorMsg,
const QString& failedUrl)
{
qDebug() << "onLoadError, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
<< ", errorCode:" << errorCode;
}

View File

@ -1,53 +1,23 @@
#ifndef BROWSER_H #ifndef CEFWIDGET_H
#define BROWSER_H #define CEFWIDGET_H
#include <QWidget> #include <QWidget>
#include <QLayout> #include <QVBoxLayout>
#include <QCloseEvent> #include <QApplication>
#include <QMessageBox>
#include <QJsonDocument> class CefWidget : public QWidget
#include "CefviewWidget.h"
#include <QMainWindow>
class CefWidget : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
CefWidget(QWidget *parent = nullptr); CefWidget(QWidget *parent = nullptr);
~CefWidget(); ~CefWidget();
void WaitCefQuit();
private: private:
void initBrowser(); void initBrowser();
CefViewWidget* m_viewWidget={}; //CefRefPtr<SimpleHandler> simple_handler_;
QWidget* m_centralWidget={}; QWidget* widget;
// QCefView slots protected:
protected slots: void resizeEvent(QResizeEvent *event) override;
void onInvokeMethod(const QCefBrowserId &browserId, void closeEvent(QCloseEvent* ev) override;
const QCefFrameId &frameId,
const QString &method,
const QVariantList &arguments);
void onQCefUrlRequest(const QCefBrowserId &browserId, const QCefFrameId &frameId, const QString &url);
void onQCefQueryRequest(const QCefBrowserId &browserId, const QCefFrameId &frameId, const QCefQuery &query);
void onJavascriptResult(const QCefBrowserId &browserId,
const QCefFrameId &frameId,
const QString &context,
const QVariant &result);
void onLoadingStateChanged(const QCefBrowserId &browserId, bool isLoading, bool canGoBack, bool canGoForward);
void onLoadStart(const QCefBrowserId &browserId, const QCefFrameId &frameId, bool isMainFrame, int transitionType);
void onLoadEnd(const QCefBrowserId &browserId, const QCefFrameId &frameId, bool isMainFrame, int httpStatusCode);
void onLoadError(const QCefBrowserId &browserId,
const QCefFrameId &frameId,
bool isMainFrame,
int errorCode,
const QString &errorMsg,
const QString &failedUrl);
}; };
#endif #endif

View File

@ -1,18 +1,18 @@
#include "CefDownloadManager.h" #include "DownloadManager.h"
#include <QDebug> #include <QDebug>
CefDownloadManager& DownloadManager&
CefDownloadManager::getInstance() DownloadManager::getInstance()
{ {
static CefDownloadManager s_instance; static DownloadManager s_instance;
return s_instance; return s_instance;
} }
void void
CefDownloadManager::AddNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item) DownloadManager::AddNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item)
{ {
qDebug() << "downloadManager::AddNewDownloadItem:" qDebug() << "DownloadManager::AddNewDownloadItem:"
<< " id: " << item->id() << "\n" << " id: " << item->id() << "\n"
<< " name: " << item->suggestedFileName() << "\n" << " name: " << item->suggestedFileName() << "\n"
<< " path: " << item->fullPath() << "\n" << " path: " << item->fullPath() << "\n"
@ -26,9 +26,9 @@ CefDownloadManager::AddNewDownloadItem(const QSharedPointer<QCefDownloadItem>& i
} }
void void
CefDownloadManager::UpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item) DownloadManager::UpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item)
{ {
qDebug() << "downloadManager::UpdateDownloadItem:" qDebug() << "DownloadManager::UpdateDownloadItem:"
<< " id: " << item->id() << "\n" << " id: " << item->id() << "\n"
<< " name: " << item->suggestedFileName() << "\n" << " name: " << item->suggestedFileName() << "\n"
<< " path: " << item->fullPath() << "\n" << " path: " << item->fullPath() << "\n"
@ -41,9 +41,9 @@ CefDownloadManager::UpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& i
m_mapDownloadingItem.remove(item->id()); m_mapDownloadingItem.remove(item->id());
} }
CefDownloadManager::CefDownloadManager() {} DownloadManager::DownloadManager() {}
CefDownloadManager::~CefDownloadManager() DownloadManager::~DownloadManager()
{ {
for (auto& item : m_mapDownloadingItem) { for (auto& item : m_mapDownloadingItem) {
item->cancel(); item->cancel();

View File

@ -1,5 +1,5 @@
#ifndef CEFDOWNLOADMANAGER_H #ifndef DOWNLOADMANAGER_H
#define CEFDOWNLOADMANAGER_H #define DOWNLOADMANAGER_H
#pragma once #pragma once
#include <QMap> #include <QMap>
@ -7,18 +7,18 @@
#include <QCefDownloadItem.h> #include <QCefDownloadItem.h>
class CefDownloadManager class DownloadManager
{ {
public: public:
static CefDownloadManager& getInstance(); static DownloadManager& getInstance();
void AddNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item); void AddNewDownloadItem(const QSharedPointer<QCefDownloadItem>& item);
void UpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item); void UpdateDownloadItem(const QSharedPointer<QCefDownloadItem>& item);
private: private:
CefDownloadManager(); DownloadManager();
~CefDownloadManager(); ~DownloadManager();
QMap<qint32, QSharedPointer<QCefDownloadItem>> m_mapDownloadingItem; QMap<qint32, QSharedPointer<QCefDownloadItem>> m_mapDownloadingItem;
}; };

317
src/Cef/MainWindow.cpp Normal file
View File

@ -0,0 +1,317 @@
#include "MainWindow.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QHBoxLayout>
#include <QJsonDocument>
#include <QJsonValue>
#include <QMessageBox>
#include <QRandomGenerator>
#include <QCefContext.h>
#define URL_ROOT "http://QCefViewDoc"
#define LEFT_INDEX_URL URL_ROOT "/left.html"
#define RIGHT_INDEX_URL URL_ROOT "/right.html"
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent /*, Qt::FramelessWindowHint*/)
{
m_ui.setupUi(this);
#ifdef Q_OS_MACOS
this->m_ui.nativeContainer->setContentsMargins(0, 28, 0, 0);
#endif
setupWindow();
// setWindowFlags(Qt::FramelessWindowHint);
// setAttribute(Qt::WA_TranslucentBackground);
connect(m_ui.btn_showDevTools, &QPushButton::clicked, this, &MainWindow::onBtnShowDevToolsClicked);
connect(m_ui.btn_reloadRight, &QPushButton::clicked, this, &MainWindow::onBtnReloadRightViewClicked);
connect(m_ui.btn_recreateRight, &QPushButton::clicked, this, &MainWindow::onBtnRecreateRightViewClicked);
connect(m_ui.btn_changeColor, &QPushButton::clicked, this, &MainWindow::onBtnChangeColorClicked);
connect(m_ui.btn_setFocus, &QPushButton::clicked, this, &MainWindow::onBtnSetFocusClicked);
connect(m_ui.btn_callJSCode, &QPushButton::clicked, this, &MainWindow::onBtnCallJSCodeClicked);
connect(m_ui.btn_newBrowser, &QPushButton::clicked, this, &MainWindow::onBtnNewBrowserClicked);
connect(m_ui.btn_quitApp, &QPushButton::clicked, qApp, &QCoreApplication::quit);
// build the path to the web resource
QDir dir = QCoreApplication::applicationDirPath();
#if defined(Q_OS_MACOS)
QString webResourceDir = /*QString("file://") +*/ QDir::toNativeSeparators(dir.filePath("../Resources/webres"));
#else
QString webResourceDir = /*QString("file://") +*/ QDir::toNativeSeparators(dir.filePath("webres"));
#endif
// add a local folder to URL map (global)
QCefContext::instance()->addLocalFolderResource(webResourceDir, URL_ROOT);
createLeftCefView();
createRightCefView();
}
MainWindow::~MainWindow() {}
void
MainWindow::createLeftCefView()
{
if (m_pLeftCefViewWidget) {
m_pLeftCefViewWidget->deleteLater();
m_pLeftCefViewWidget = nullptr;
}
QCefSetting setting;
setting.setWindowlessFrameRate(1000);
setting.setHardwareAcceleration(false);
// setting.setBackgroundColor(Qt::magenta);
m_pLeftCefViewWidget = new CefViewWidget("https://www.testufo.com/", &setting, this);
// connect the invokeMethod to the slot
connect(m_pLeftCefViewWidget, &QCefView::invokeMethod, this, &MainWindow::onInvokeMethod);
// connect the cefQueryRequest to the slot
connect(m_pLeftCefViewWidget, &QCefView::cefUrlRequest, this, &MainWindow::onQCefUrlRequest);
connect(m_pLeftCefViewWidget, &QCefView::cefQueryRequest, this, &MainWindow::onQCefQueryRequest);
connect(m_pLeftCefViewWidget, &QCefView::reportJavascriptResult, this, &MainWindow::onJavascriptResult);
connect(m_pLeftCefViewWidget, &QCefView::loadStart, this, &MainWindow::onLoadStart);
connect(m_pLeftCefViewWidget, &QCefView::loadEnd, this, &MainWindow::onLoadEnd);
connect(m_pLeftCefViewWidget, &QCefView::loadError, this, &MainWindow::onLoadError);
m_ui.leftCefViewContainer->layout()->addWidget(m_pLeftCefViewWidget);
}
void
MainWindow::createRightCefView()
{
if (m_pRightCefViewWidget) {
m_pRightCefViewWidget->deleteLater();
m_pRightCefViewWidget = nullptr;
}
// build settings for per QCefView
QCefSetting setting;
#if CEF_VERSION_MAJOR < 100
setting.setPlugins(false);
#endif
setting.setWindowlessFrameRate(1000);
setting.setHardwareAcceleration(true);
QColor background(0, 255, 0, 255);
setting.setBackgroundColor(background);
// create the QCefView widget and add it to the layout container
// m_pRightCefViewWidget = new QCefView(RIGHT_INDEX_URL, &setting, this);
m_pRightCefViewWidget = new QCefView("https://www.testufo.com/", &setting, this);
// auto vl = new QVBoxLayout(m_pRightCefViewWidget);
// auto btn = new QPushButton("TEST BUTTON OVERLAY", m_pRightCefViewWidget);
//// btn->setFixedSize(320, 240);
// btn->setStyleSheet("background-color: rgba(1, 1, 1, 0);");
// btn->setAttribute(Qt::WA_TranslucentBackground);
// btn->setWindowFlags(Qt::FramelessWindowHint);
// btn->setAttribute(Qt::WA_NoSystemBackground);
// vl->setAlignment(Qt::AlignVCenter);
// vl->addWidget(btn);
// m_pRightCefViewWidget->setLayout(vl);
// all the following values will disable the context menu for both NCW and OSR mode
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::NoContextMenu);
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::CustomContextMenu);
// m_pRightCefViewWidget->setContextMenuPolicy(Qt::PreventContextMenu);
m_pRightCefViewWidget->setContextMenuPolicy(Qt::DefaultContextMenu);
// add the QCefView widget to the layout
m_ui.rightCefViewContainer->layout()->addWidget(m_pRightCefViewWidget);
}
void
MainWindow::onInvokeMethod(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
const QString& method,
const QVariantList& arguments)
{
// extract the arguments and dispatch the invocation to corresponding handler
if (0 == method.compare("TestMethod")) {
QString title("QCef InvokeMethod Notify");
QString text = QString("================== Current Thread: QT_UI ==================\r\n"
"Frame: %1\r\n"
"Method: %2\r\n"
"Arguments:\r\n")
.arg(frameId)
.arg(method);
for (int i = 0; i < arguments.size(); i++) {
auto jv = QJsonValue::fromVariant(arguments[i]);
// clang-format off
text.append(
QString("%1 Type:%2, Value:%3\r\n")
.arg(i).arg(arguments[i].typeName()).arg(arguments[i].toString())
);
// clang-format on
}
auto jsonValue = QJsonDocument::fromVariant(arguments);
auto jsonString = QString(jsonValue.toJson());
text.append(QString("\r\nArguments List in JSON format:\r\n%1").arg(jsonString));
QMessageBox::information(this->window(), title, text);
} else {
}
}
void
MainWindow::onQCefUrlRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QString& url)
{
QString title("QCef URL Request");
QString text = QString("Current Thread: QT_UI\r\n"
"URL: %1")
.arg(url);
QMessageBox::information(this->window(), title, text);
}
void
MainWindow::onQCefQueryRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QCefQuery& query)
{
QString title("QCef Query Request");
QString text = QString("Current Thread: QT_UI\r\n"
"Query: %1")
.arg(query.request());
QMessageBox::information(this->window(), title, text);
QString response = query.request().toUpper();
query.setResponseResult(true, response);
m_pLeftCefViewWidget->responseQCefQuery(query);
}
void
MainWindow::onJavascriptResult(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
const QString& context,
const QVariant& result)
{
auto jsonValue = QJsonDocument::fromVariant(result);
auto jsonString = QString(jsonValue.toJson());
QString title("Javascript result notification");
QString text = QString("Context: %1\r\nResult in JSON format:\r\n%2").arg(context).arg(jsonString);
QMessageBox::information(this->window(), title, text);
}
void
MainWindow::onLoadingStateChanged(const QCefBrowserId& browserId, bool isLoading, bool canGoBack, bool canGoForward)
{
qDebug() << "onLoadingStateChanged, browserId:" << browserId << ", isLoading:" << isLoading
<< ", canGoBack:" << canGoBack << ", canGoForward:" << canGoForward;
}
void
MainWindow::onLoadStart(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
bool isMainFrame,
int transitionType)
{
qDebug() << "onLoadStart, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
<< ", transitionType:" << transitionType;
}
void
MainWindow::onLoadEnd(const QCefBrowserId& browserId, const QCefFrameId& frameId, bool isMainFrame, int httpStatusCode)
{
qDebug() << "onLoadEnd, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
<< ", httpStatusCode:" << httpStatusCode;
}
void
MainWindow::onLoadError(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
bool isMainFrame,
int errorCode,
const QString& errorMsg,
const QString& failedUrl)
{
qDebug() << "onLoadError, browserId:" << browserId << ", frameId:" << frameId << ", isMainFrame:" << isMainFrame
<< ", errorCode:" << errorCode;
}
void
MainWindow::onBtnShowDevToolsClicked()
{
if (m_pLeftCefViewWidget) {
m_pLeftCefViewWidget->showDevTools();
}
}
void
MainWindow::onBtnReloadRightViewClicked()
{
if (m_pRightCefViewWidget) {
m_pRightCefViewWidget->navigateToUrl("https://www.google.com");
}
}
void
MainWindow::onBtnRecreateRightViewClicked()
{
createRightCefView();
}
void
MainWindow::onBtnChangeColorClicked()
{
if (m_pLeftCefViewWidget) {
// create a random color
QColor color(QRandomGenerator::global()->generate());
// create the cef event and set the arguments
QCefEvent event("colorChange");
event.arguments().append(QVariant::fromValue(color.name(QColor::HexArgb)));
// broadcast the event to all frames in all browsers created by this QCefView widget
m_pLeftCefViewWidget->broadcastEvent(event);
}
}
void
MainWindow::onBtnCallJSCodeClicked()
{
QString context = "helloQCefView";
QString code = "alert('hello QCefView'); return {k1: 'str', k2: true, k3: 100};";
m_pLeftCefViewWidget->executeJavascriptWithResult(QCefView::MainFrameID, code, "", context);
}
void
MainWindow::onBtnSetFocusClicked()
{
if (m_pLeftCefViewWidget) {
m_pLeftCefViewWidget->setFocus();
}
}
void
MainWindow::onBtnNewBrowserClicked()
{
QMainWindow* w = new QMainWindow(nullptr);
w->setAttribute(Qt::WA_DeleteOnClose);
QCefSetting settings;
QCefView* view = new QCefView("https://cefview.github.io/QCefView/", &settings, w);
w->setCentralWidget(view);
w->resize(1024, 768);
w->show();
}
#ifndef Q_OS_MACOS
void
MainWindow::setupWindow()
{
}
#endif

77
src/Cef/MainWindow.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef QCEFVIEWTEST_H
#define QCEFVIEWTEST_H
#include <QCloseEvent>
#include <QMainWindow>
#include "ui_MainWindow.h"
#include "CefViewWidget.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = 0);
~MainWindow();
protected:
void createLeftCefView();
void createRightCefView();
void setupWindow();
// QCefView slots
protected slots:
void onInvokeMethod(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
const QString& method,
const QVariantList& arguments);
void onQCefUrlRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QString& url);
void onQCefQueryRequest(const QCefBrowserId& browserId, const QCefFrameId& frameId, const QCefQuery& query);
void onJavascriptResult(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
const QString& context,
const QVariant& result);
void onLoadingStateChanged(const QCefBrowserId& browserId, bool isLoading, bool canGoBack, bool canGoForward);
void onLoadStart(const QCefBrowserId& browserId, const QCefFrameId& frameId, bool isMainFrame, int transitionType);
void onLoadEnd(const QCefBrowserId& browserId, const QCefFrameId& frameId, bool isMainFrame, int httpStatusCode);
void onLoadError(const QCefBrowserId& browserId,
const QCefFrameId& frameId,
bool isMainFrame,
int errorCode,
const QString& errorMsg,
const QString& failedUrl);
// ui slots
protected slots:
void onBtnShowDevToolsClicked();
void onBtnReloadRightViewClicked();
void onBtnRecreateRightViewClicked();
void onBtnChangeColorClicked();
void onBtnSetFocusClicked();
void onBtnCallJSCodeClicked();
void onBtnNewBrowserClicked();
private:
Ui::MainWindow m_ui;
QCefView* m_pLeftCefViewWidget = nullptr;
QCefView* m_pRightCefViewWidget = nullptr;
};
#endif // QCEFVIEWTEST_H

250
src/Cef/MainWindow.ui Normal file
View File

@ -0,0 +1,250 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1280</width>
<height>900</height>
</rect>
</property>
<property name="windowTitle">
<string>QCefViewTest</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<widget class="QWidget" name="nativeContainer" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">
#nativeContainer {
background-color: rgb(170, 255, 255);
}
</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_nativeContainer">
<property name="spacing">
<number>6</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="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">
#label{
font: 12pt &quot;MS Shell Dlg 2&quot;;
}
</string>
</property>
<property name="text">
<string>Native Area</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_showDevTools">
<property name="text">
<string>Show Left DevTools</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_reloadRight">
<property name="text">
<string>Reload Right QCefView</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_recreateRight">
<property name="text">
<string>Recreate Right QCefView</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_changeColor">
<property name="text">
<string>ChangeColor</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item>
<widget class="QPushButton" name="btn_setFocus">
<property name="text">
<string>SetFocus</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_2"/>
</item>
<item>
<widget class="QPushButton" name="btn_callJSCode">
<property name="text">
<string>CallJSCode</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_3"/>
</item>
<item>
<widget class="QPushButton" name="btn_newBrowser">
<property name="text">
<string>NewBrowser</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btn_quitApp">
<property name="text">
<string>Exit App</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="leftCefViewContainer" native="true">
<property name="styleSheet">
<string notr="true">QWidget#leftCefViewContainer {
background-color: rgb(217, 183, 255);
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_cefContainer">
<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>
</layout>
</widget>
<widget class="QWidget" name="rightCefViewContainer" native="true">
<property name="styleSheet">
<string notr="true">QWidget#rightCefViewContainer {
background-color: rgb(217, 183, 255);
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_cefContainer_2">
<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>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<tabstops>
<tabstop>btn_showDevTools</tabstop>
<tabstop>btn_reloadRight</tabstop>
<tabstop>btn_recreateRight</tabstop>
<tabstop>btn_changeColor</tabstop>
<tabstop>lineEdit</tabstop>
<tabstop>lineEdit_2</tabstop>
<tabstop>btn_callJSCode</tabstop>
<tabstop>lineEdit_3</tabstop>
<tabstop>btn_newBrowser</tabstop>
<tabstop>btn_quitApp</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- This tag is required for XAML islands usage in the process for media scenarios. -->
<!-- This version corresponds to the Windows 10 May 2019 Update. -->
<maxversiontested Id="10.0.18362.0"/>
</application>
</compatibility>
</assembly>

20
src/ctai.exe.manifest Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<!--The compatibility section will be merged from build/win/compatibility.manifest -->
<dependency>
<dependentAssembly>
<assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@ -4,83 +4,34 @@
#include "sui_base_ex.h" #include "sui_base_ex.h"
#include "ctai.h" #include "ctai.h"
#include <QApplication> #include <QApplication>
#include "QCefContext.h"
#include "Cef/CefWidget.h"
// void init_Browser(QApplication& instance,int argc, char *argv[]){
// // build QCefConfig
// QCefConfig config;
// // set user agent
// config.setUserAgent("QCefViewTest");
// // set log level
// config.setLogLevel(QCefConfig::LOGSEVERITY_DEFAULT);
// // set JSBridge object name (default value is CefViewClient)
// config.setBridgeObjectName("CallBridge");
// // set Built-in scheme name (default value is CefView)
// config.setBuiltinSchemeName("CefView");
// // port for remote debugging (default is 0 and means to disable remote debugging)
// //config.setRemoteDebuggingPort(9000);
// // set background color for all browsers
// // (QCefSetting.setBackgroundColor will overwrite this value for specified browser instance)
// // config.setBackgroundColor(Qt::lightGray);
// // WindowlessRenderingEnabled is set to true by default,
// // set to false to disable the OSR mode
// //config.setWindowlessRenderingEnabled(true);
// //config.addCommandLineSwitch("no-sandbox");
// // add command line args, you can any cef supported switches or parameters
// //config.addCommandLineSwitch("use-mock-keychain");
// //config.addCommandLineSwitch("disable-gpu");
// // config.addCommandLineSwitch("enable-media-stream");
// // config.addCommandLineSwitch("allow-file-access-from-files");
// // config.addCommandLineSwitch("disable-spell-checking");
// // config.addCommandLineSwitch("disable-site-isolation-trials");
// // config.addCommandLineSwitch("enable-aggressive-domstorage-flushing");
// //config.addCommandLineSwitchWithValue("renderer-process-limit", "1");
// // allow remote debugging
// //config.addCommandLineSwitchWithValue("remote-allow-origins", "*");
// // config.addCommandLineSwitchWithValue("disable-features", "BlinkGenPropertyTrees,TranslateUI,site-per-process");
// // set cache folder
// config.setCachePath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation));
// // create QCefContext instance with config,
// // the lifecycle of cefContext must be the same as QApplication instance
// QCefContext cefContext(&instance, argc, argv, &config);
// }
// int main(int argc, char *argv[])
// {
// QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
// qputenv("QT_QPA_PLATFORM", "windows:fontengine=freetype");
// QApplication a(argc, argv);
// //加载语言包
// QTranslator qtBaseTranslator;
// if (!qtBaseTranslator.load(QStringLiteral(":/res/translator/qtbase_zh_CN.qm")))
// {
// // 处理加载翻译文件失败的情况
// qDebug() << "Failed to load translation file.";
// return -1;
// }
// a.installTranslator(&qtBaseTranslator);
// //初始化浏览器
// init_Browser(a,argc,argv);
// //读取窗体的配置并初始化
// sui_init_config();
// ctai x;
// x.init_layout();
// // 仅限于windows平台
// #if defined(__WIN32__)
// x.title()->set_type(QD_TYPE::QD_EXIT);
// #endif
// x.show();
// CefWidget w;
// w.show();
// return a.exec();
// }
#include <QCefContext.h> #include <QCefContext.h>
int #include "cef/MainWindow.h"
main(int argc, char* argv[])
int main(int argc, char *argv[])
{ {
#if (QT_VERSION <= QT_VERSION_CHECK(6, 0, 0)) QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
qputenv("QT_QPA_PLATFORM", "windows:fontengine=freetype");
QApplication a(argc, argv);
// 加载语言包
QTranslator qtBaseTranslator;
if (!qtBaseTranslator.load(QStringLiteral(":/res/translator/qtbase_zh_CN.qm")))
{
// 处理加载翻译文件失败的情况
qDebug() << "Failed to load translation file.";
return -1;
}
a.installTranslator(&qtBaseTranslator);
// 读取窗体的配置并初始化
sui_init_config();
ctai x;
x.init_layout();
// 仅限于windows平台
#if defined(__WIN32__)
x.title()->set_type(QD_TYPE::QD_EXIT);
#endif
x.show();
//初始化CEF
#if (QT_VERSION <= QT_VERSION_CHECK(6, 0, 0))
// For off-screen rendering, Qt::AA_EnableHighDpiScaling must be enabled. If not, // For off-screen rendering, Qt::AA_EnableHighDpiScaling must be enabled. If not,
// then all devicePixelRatio methods will always return 1.0, // then all devicePixelRatio methods will always return 1.0,
// so CEF will not scale the web content // so CEF will not scale the web content
@ -90,10 +41,6 @@ main(int argc, char* argv[])
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif #endif
#endif #endif
// create QApplication instance
QApplication a(argc, argv);
// build QCefConfig // build QCefConfig
QCefConfig config; QCefConfig config;
// set user agent // set user agent
@ -113,9 +60,16 @@ main(int argc, char* argv[])
// WindowlessRenderingEnabled is set to true by default, // WindowlessRenderingEnabled is set to true by default,
// set to false to disable the OSR mode // set to false to disable the OSR mode
config.setWindowlessRenderingEnabled(true); config.setWindowlessRenderingEnabled(true);
// add command line args, you can any cef supported switches or parameters // add command line args, you can any cef supported switches or parameters
config.addCommandLineSwitch("use-mock-keychain"); config.addCommandLineSwitch("use-mock-keychain");
config.addCommandLineSwitch("single-process");
config.addCommandLineSwitch("enable-gpu");
config.addCommandLineSwitch("enable-gpu-rasterization");
config.addCommandLineSwitch("enable-webgl");
config.addCommandLineSwitch("enable-impl-side-painting");
config.addCommandLineSwitch("disable-software-rasterizer");
config.addCommandLineSwitch("multi-threaded-message-loop");
// config.addCommandLineSwitch("disable-gpu"); // config.addCommandLineSwitch("disable-gpu");
// config.addCommandLineSwitch("enable-media-stream"); // config.addCommandLineSwitch("enable-media-stream");
// config.addCommandLineSwitch("allow-file-access-from-files"); // config.addCommandLineSwitch("allow-file-access-from-files");
@ -134,11 +88,8 @@ main(int argc, char* argv[])
// the lifecycle of cefContext must be the same as QApplication instance // the lifecycle of cefContext must be the same as QApplication instance
QCefContext cefContext(&a, argc, argv, &config); QCefContext cefContext(&a, argc, argv, &config);
// application window MainWindow w;
CefWidget w;
w.show(); w.show();
// flying
return a.exec(); return a.exec();
} }