> 技术文档 > WebView2嵌入Qt以使用Edge替代webEngine(Qt添加外部运行库,以WebView2为例)_qt webview2

WebView2嵌入Qt以使用Edge替代webEngine(Qt添加外部运行库,以WebView2为例)_qt webview2


将WebView2加入Qt编译并运行示例

  • 1. 下载组件
  • 2. 获取WebView2包
    • 方法一. 直接解压缩.nupkg支持包
    • 方法二. 使用vs安装NuGet程序包获取
    • 最终,我们可以得到下面两个运行WebView2的必要支持包。
  • 3. 嵌入Qt工程
  • 将WebView2加入Qt编译
  • 运行示例工程

日志:1. 最近学习做项目时深感webEngine加载网页的缓慢和编译后的臃肿,所以尝试着使用WebView2调用Edge浏览器来减减负。
2. 想要添加其他运行库同样可以参照此方法

1. 下载组件

  1. Microsoft Edge WebView2
  2. 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解压缩。
`Microsoft.Web.WebView2.1.0.902.49

方法二. 使用vs安装NuGet程序包获取

打开下载的WebView2Samples示例包,打开如下路径(WebView2Samples\\GettingStartedGuides\\Win32_GettingStarted),此为WebView2Samples的原始示例工程。使用vs打开此示例工程,这里借鉴微软官方的配置教程,Win32 应用中的 WebView2 入门。
Win32_GettingStarted
在使用安装必要组件后,此时打开工程目录会发现多了一个packages文件夹。
WebView2Samples\\GettingStartedGuides\\Win32_GettingStarted

最终,我们可以得到下面两个运行WebView2的必要支持包。

必要支持包

3. 嵌入Qt工程

如何新建一个Qt工程这里不再赘述,我们直接开始嵌入WebView2。

将WebView2加入Qt编译

  1. 将packages包复制到所在工程路径,我的复制在external/packages处。
    packages包路径

  2. 这里我使用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 #include #include #include #include #include #include using namespace Microsoft::WRL;namespace Ui {class mapWeb;}class mapWeb : public QWidget{Q_OBJECTpublic: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);}