将WebView2加入Qt编译并运行示例
日志:1. 最近学习做项目时深感webEngine加载网页的缓慢和编译后的臃肿,所以尝试着使用WebView2调用Edge浏览器来减减负。
2. 想要添加其他运行库同样可以参照此方法
1. 下载组件
- Microsoft Edge WebView2
- WebView2Samples,此为WebView2所有功能的示例工程(可以选择不下载)。
2. 获取WebView2包
有两种方法供选择,一种是直接解压缩.nupkg支持包,另一种是使用vs打开WebView2Samples中的示例工程后安装NuGet程序包获取。
方法一. 直接解压缩.nupkg支持包
进入网页后点击右侧的下载按钮,来下载下面两个支持包
Microsoft.Web.WebView2.1.0.902.49
Microsoft.Windows.ImplementationLibrary.1.0.191107.2
下载后发现是.nupkg文件,可以直接使用解压缩软件解压。这里我使用Bandizip解压缩。
方法二. 使用vs安装NuGet程序包获取
打开下载的WebView2Samples示例包,打开如下路径(WebView2Samples\GettingStartedGuides\Win32_GettingStarted),此为WebView2Samples的原始示例工程。使用vs打开此示例工程,这里借鉴微软官方的配置教程,Win32 应用中的 WebView2 入门。
在使用<管理 NuGet程序包>安装必要组件后,此时打开工程目录会发现多了一个packages文件夹。
最终,我们可以得到下面两个运行WebView2的必要支持包。
3. 嵌入Qt工程
如何新建一个Qt工程这里不再赘述,我们直接开始嵌入WebView2。
将WebView2加入Qt编译
-
将packages包复制到所在工程路径,我的复制在external/packages处。
-
这里我使用CMake嵌入,至于Qt的qmake工程可以借鉴CMakeLists.txt文件,应该能够很轻松的嵌入。
下面是需要在CMakeLists.txt添加的内容。Map_Upper_Computer为我的项目的名称。
# 设置扩展包路径,CMAKE_CURRENT_SOURCE_DIR为工程所在路径,一般默认包含子啊工程中,不必额外设置。
set(CMAKE_EXTERNAL_PACKAGES ${CMAKE_CURRENT_SOURCE_DIR}/external/packages)
# 添加扩展包头文件目录。一般运行库所需的头文件
include_directories(${CMAKE_EXTERNAL_PACKAGES}/Microsoft.Web.WebView2.1.0.2957.106/build/native/include)
include_directories(${CMAKE_EXTERNAL_PACKAGES}/Microsoft.Windows.ImplementationLibrary.1.0.240803.1/include)
# 添加扩展包库目录,根据自身所在平台选择arm64/x64/x86,为lib文件所在目录
link_directories(${CMAKE_EXTERNAL_PACKAGES}/Microsoft.Web.WebView2.1.0.2957.106/build/native/x64)
# 链接lib文件可以和原有的合并,即
target_link_libraries(Map_Upper_Computer PRIVATE
Qt${QT_VERSION_MAJOR}::Widgets
Qt${QT_VERSION_MAJOR}::WebEngineWidgets
Qt${QT_VERSION_MAJOR}::WebEngineCore
Qt${QT_VERSION_MAJOR}::SerialPort
Qt${QT_VERSION_MAJOR}::Qml
Qt${QT_VERSION_MAJOR}::Quick
WebView2LoaderStatic.lib
WebView2Loader.dll.lib
)
运行示例工程
这里给出嵌入项目的示例代码,有些简陋,验证是否移植成功,主打一个能用就行。
头文件
#ifndef MAPWEB_H
#define MAPWEB_H
#include <QWidget>
#include <QProcess>
#include <windows.h>
#include <wrl.h>
#include <wil/com.h>
#include <WebView2.h>
#include <QResizeEvent>
using namespace Microsoft::WRL;
namespace Ui {
class mapWeb;
}
class mapWeb : public QWidget
{
Q_OBJECT
public:
explicit mapWeb(QWidget* parent = nullptr);
~mapWeb();
private:
Ui::mapWeb* ui;
wil::com_ptr<ICoreWebView2Controller> webviewController;
wil::com_ptr<ICoreWebView2> webview;
void initializeWebView2();
void resizeEvent(QResizeEvent* event);
};
#endif // MAPWEB_H
源文件
#include "mapWeb.h"
#include "ui_mapweb.h"
mapWeb::mapWeb(QWidget* parent)
: QWidget(parent), ui(new Ui::mapWeb)
{
ui->setupUi(this);
initializeWebView2();
}
mapWeb::~mapWeb()
{
if (webviewController) {
webviewController = nullptr;
}
if (webview) {
webview = nullptr;
}
delete ui;
}
void mapWeb::initializeWebView2()
{
HWND hwnd = (HWND)this->winId();
// WebView2 用户数据存储路径
LPCWSTR userDataFolder = L"C:\\ProgramData\\Cache";
// 创建 WebView2 控制器
CreateCoreWebView2EnvironmentWithOptions(nullptr, userDataFolder, nullptr,
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[this, hwnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT
{
if (FAILED(result)) {
qDebug() << "WebView2 环境创建失败: " << result;
return result;
}
env->CreateCoreWebView2Controller(hwnd, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[this, hwnd](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT
{
if (FAILED(result) || !controller) {
qDebug() << "WebView2 控制器创建失败: " << result;
return result;
}
webviewController = controller;
webviewController->get_CoreWebView2(&webview);
// 设置创建的框体的大小
RECT bounds;
GetClientRect(hwnd, &bounds);
webviewController->put_Bounds(bounds);
webview->Navigate(L"https://www.bing.com");
return S_OK;
}).Get());
return S_OK;
}).Get());
}
// 监视框体变动以实时更改界面大小
void mapWeb::resizeEvent(QResizeEvent* event)
{
if (webviewController) {
RECT bounds;
GetClientRect((HWND)this->winId(), &bounds);
webviewController->put_Bounds(bounds);
}
QWidget::resizeEvent(event);
}