最近领导想在 Qt 的交易客户端上嵌入 web 页面
有的做成 QWindow 可以独立打开关闭,有的做成 QWidget 可以添加到 QTabWidget 里
Qt 想使用 Web 的话,可以选择 QWebEngine、CEF、WebView2
领导用的是 mac 上用 parallels desktop 虚拟出来的 Windows 11,性能很差
测试下来,发现 QWebEngine 稍卡、cef 很流畅、WebView2 最流畅
用 https://web.basemark.com/ 跑的分
QtWebEngine 使用的 6.8.3 vs2022 x64 release
cef 用的 https://github.com/CefView/QCefView
写了一些 demo,包括 C++ 和 JS 通信的,反正最后没用上,就不提了
最终是用了微软的 WebVIew2
优点是性能和原生的 chrome 几乎没差别(-5%左右),打包变小了(减少了200M左右)
缺点是不能跨平台,只能在 windows 上用
接下来重点说下 WebView2
https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/?form=MA13LH#download
https://github.com/MicrosoftEdge/WebView2Samples.git
https://www.nuget.org/packages/Microsoft.Web.WebView2
https://www.nuget.org/packages/Microsoft.Windows.ImplementationLibrary


进入网页后点击右侧的下载按钮,来下载下面两个支持包
下载后发现是.nupkg文件,右键用 7-zip 解压
webview.h
x
using namespace Microsoft::WRL;
class WebView : public QWidget{ Q_OBJECTpublic: explicit WebView(QWidget* parent = nullptr, QString url = QString()); ~WebView(); void sendJson(QString str);private: wil::com_ptr<ICoreWebView2Controller> webviewController; wil::com_ptr<ICoreWebView2> webview; wil::com_ptr<ICoreWebView2Settings> settings; QString m_url; void initializeWebView2(); void resizeEvent(QResizeEvent* event);};webview.cpp
xxxxxxxxxx
WebView::WebView(QWidget* parent, QString url) : QWidget(parent), m_url(url){ initializeWebView2();}
WebView::~WebView(){ if (webviewController) { webviewController = nullptr; } if (webview) { webview = nullptr; }}
void WebView::sendJson(QString str){ webview->PostWebMessageAsJson(str.toStdWString().c_str());}
void WebView::initializeWebView2(){ HWND hwnd = (HWND)this->winId();
// WebView2 用户数据存储路径 LPCWSTR userDataFolder = L"C:\\ProgramData\\Cache";
// 允许加载本地 html 和 js std::wstring args; args.append(L"--disable-web-security"); auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>(); options->put_AdditionalBrowserArguments(args.c_str());
CreateCoreWebView2EnvironmentWithOptions(nullptr, userDataFolder, options.Get(), 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); // 禁用 F12 调试 webview->get_Settings(&settings); settings->put_AreDevToolsEnabled(false);
// 设置创建的框体的大小 RECT bounds; GetClientRect(hwnd, &bounds); webviewController->put_Bounds(bounds);
std::wstring htmlPath = m_url.toStdWString(); webview->Navigate(htmlPath.c_str());
return S_OK; }).Get());
return S_OK; }).Get());}
void WebView::resizeEvent(QResizeEvent* event){ if (webviewController) { RECT bounds; GetClientRect((HWND)this->winId(), &bounds); webviewController->put_Bounds(bounds); } QWidget::resizeEvent(event);}动态库库引入
WebView2Loader.dll.lib
头文件引入
WebView2.h
WebView2EnvironmentOptions.h
wil 目录
使用方式
WebView *view = new WebView(this, “http://www.baidu.com”);
Qt 集成 https://blog.csdn.net/Baizn/article/details/145581641
Qt 集成 https://blog.csdn.net/andybegin/article/details/134120854
JS 调用 https://learn.microsoft.com/zh-cn/microsoft-edge/webview2/how-to/communicate-btwn-web-native