WebView2 是 Microsoft 提供的一个嵌入式浏览器控件,基于 Edge (Chromium) 内核,支持在桌面应用中加载 HTML、CSS 和 JavaScript,适用于现代化的桌面应用开发。而 Windows Implementation Library (WIL) 是一个帮助开发者简化 Windows API 使用的库,在 WebView2 开发中常用于管理 COM 资源和简化错误处理。
环境准备
安装 WebView2 运行时
WebView2 依赖于 Microsoft Edge (Chromium) 内核,因此需要确保 WebView2 运行时已安装。可以通过以下方式获取:
- 下载安装 WebView2 Runtime。
- 在项目中使用固定版本运行时(Evergreen Standalone Installer)。
- 如果希望在程序中检查 WebView2 运行时是否可用,可以使用
WebView2Loader.dll
提供的 API。
安装 WebView2 和 WIL
通过 NuGet 安装 WebView2 SDK
在 Visual Studio 中,打开“NuGet 包管理器”并运行以下命令:
Install-Package Microsoft.Web.WebView2
通过 NuGet 安装 WIL(Windows Implementation Library)
Install-Package Microsoft.Windows.ImplementationLibrary
这两个库分别用于:
Microsoft.Web.WebView2
提供 WebView2 控件的接口和 API。Microsoft.Windows.ImplementationLibrary
(WIL) 让 Windows API 的使用更简单,如 COM 资源管理、错误处理等。
packages.config
说明
在 NuGet 安装 WebView2 和 WIL 后,packages.config
文件会自动更新,记录所有依赖包及其版本。示例如下:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Web.WebView2" version="1.0.2098.22" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210902.1" targetFramework="native" />
</packages>
packages.config
的作用:
- 记录 NuGet 依赖项,方便团队协作时安装相同版本的依赖包。
- 便于在新环境中自动还原依赖项,确保构建时不会缺少库。
可以使用 nuget restore
命令自动安装 packages.config
里定义的所有包:
nuget restore packages.config -PackagesDirectory packages
WebView2 依赖的 DLL 文件
WebView2 运行时通常包含多个 DLL 文件,最重要的是 WebView2Loader.dll
。在使用 WebView2 时,需要确保这些动态库文件可用:
WebView2Loader.dll 位置
在 Microsoft.Web.WebView2
NuGet 包安装后,你可以在以下路径找到 WebView2Loader.dll
:
runtimes\win-x64\native\WebView2Loader.dll
这个文件必须包含在你的应用程序的可执行目录中,否则 WebView2 可能无法正常运行。你可以手动复制 DLL,或者在 CMake 或 MSBuild 配置中自动包含该文件。
如何确保 WebView2Loader.dll 在运行时可用?
- 将
WebView2Loader.dll
复制到应用程序的输出目录 (Debug/Release
目录)。 - 在 C++ 代码中检查
WebView2Loader.dll
是否可用,如果缺失则提示用户安装 WebView2 运行时。
1. WebView2 的关键特点
- 基于 Chromium:依赖 Microsoft Edge (Chromium) 引擎,支持最新的 Web 标准。
- 双向通信:原生代码和 JavaScript 可以互相调用。
- 独立版本:可以嵌入固定的 WebView2 运行时,避免依赖用户系统中的 Edge。
- 多平台支持:适用于 Win32、WPF、WinForms 和 MFC 等不同框架。
2. WebView2 的使用场景
混合应用开发
- 桌面程序中嵌入复杂的 Web 界面。
- 提供与服务器通信的实时动态功能。
浏览器功能
- 显示网页内容,比如帮助文档或在线资源。
- 嵌入第三方服务(如支付网关或地图服务)。
调试工具
- 在桌面工具中集成可定制的网页调试功能。
跨平台支持
- 使用统一的 HTML/JavaScript/CSS 逻辑,实现跨平台开发。
3. WebView2 的主要组成部分
- ICoreWebView2:核心接口,用于管理 WebView2 控件。
- ICoreWebView2Controller:用于控制 WebView2 的外观(例如大小和位置)。
- WebView2 环境:托管 WebView2 实例,并加载 Chromium 运行时。
4. 头文件与全局变量
在 MFC 项目中,需要包含以下头文件:
#include <wrl.h>
#include <wil/com.h>
#include "WebView2.h"
定义全局变量(用于管理 WebView2 控件):
using namespace Microsoft::WRL;
// 指向 WebView2 控制器
static wil::com_ptr<ICoreWebView2Controller> webViewController;
// 指向 WebView2 窗口
static wil::com_ptr<ICoreWebView2> webView;
5. 初始化 WebView2
初始化 COM 和 WebView2
在 OnInitDialog
方法中初始化 COM 并创建 WebView2:
BOOL CMyDialog::OnInitDialog() {
CDialogEx::OnInitDialog();
// 初始化 COM
CoInitialize(NULL);
// 传入窗口句柄
InitWebView2(this->GetSafeHwnd());
return TRUE;
}
创建 WebView2 控件
创建 InitWebView2
方法,在 MFC 窗口中加载 WebView2。
void CMyDialog::InitWebView2(HWND hwnd) {
CreateCoreWebView2EnvironmentWithOptions(
nullptr, nullptr, nullptr,
Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
[hwnd](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
if (env) {
env->CreateCoreWebView2Controller(hwnd,
Microsoft::WRL::Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
[hwnd](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
if (controller) {
webViewController = controller;
webViewController->get_CoreWebView2(&webView);
// 设置 WebView2 的大小
RECT bounds;
GetClientRect(&bounds);
webViewController->put_Bounds(bounds);
// 加载网页
webView->Navigate(L"https://www.baidu.com");
}
return S_OK;
}).Get());
}
return S_OK;
}).Get());
}
6. 释放 WebView2 和 COM 组件
在 OnDestroy
方法中调用 CoUninitialize()
释放 COM 组件,以确保 WebView2 资源正确释放。
void CMyDialog::OnDestroy() {
CDialogEx::OnDestroy();
webViewController = nullptr;
webView = nullptr;
CoUninitialize(); // 释放 COM
}
7. 处理窗口大小变化 (OnSize
)
在 MFC 窗口调整大小时,WebView2 需要随之调整大小,否则窗口内容可能会显示不完整。你可以在 OnSize
事件中更新 WebView2 控件的大小:
void CMyDialog::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
if (webViewController != nullptr) {
RECT bounds;
GetClientRect(&bounds);
webViewController->put_Bounds(bounds);
}
}
关键点解析:
OnSize
是 MFC 窗口大小调整时的回调函数。GetClientRect
获取窗口的客户区大小,并调整 WebView2 的Bounds
以匹配窗口大小。- 只有在
webViewController
已初始化的情况下,才进行调整,避免空指针错误。
8. 与 JavaScript 通信
C++ 调用 JavaScript
webView->ExecuteScript(L"alert('Hello from C++!');", nullptr);
JavaScript 调用 C++
在 C++ 中注册事件处理程序:
webView->add_WebMessageReceived(
Callback<ICoreWebView2WebMessageReceivedEventHandler>(
[](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT {
wil::unique_cotaskmem_string message;
args->get_WebMessageAsString(&message);
MessageBox(nullptr, message.get(), L"Message from JavaScript", MB_OK);
return S_OK;
}).Get(), nullptr);
在 JavaScript 中发送消息:
window.chrome.webview.postMessage("Hello from JavaScript!");
9. 设置 WebView 的外观和行为
调整大小
RECT bounds;
GetClientRect(&bounds);
webViewController->put_Bounds(bounds);
禁用右键菜单和缩放
webView->put_Settings(
Callback<ICoreWebView2Settings>(
[](ICoreWebView2Settings* settings) -> HRESULT {
settings->put_IsZoomControlEnabled(FALSE);
settings->put_AreDefaultContextMenusEnabled(FALSE);
return S_OK;
}).Get());
10. 加载本地内容
加载本地 HTML 文件
webView->Navigate(L"file:///C:/path/to/your/file.html");
加载嵌入 HTML
webView->NavigateToString(L"<html><body><h1>Hello, WebView2!</h1></body></html>");
11. 高级功能
注入 JavaScript
webView->AddScriptToExecuteOnDocumentCreated(
L"console.log('Injected Script');", nullptr);
拦截网络请求
可以通过 ICoreWebView2AddWebResourceRequestedFilter
方法拦截并处理网络请求。
总结
在本指南中,我们详细介绍了如何在 MFC 应用中集成 WebView2,并结合 WIL 进行高效开发。
关键步骤总结:
- 安装 WebView2 运行时 - 确保 WebView2 依赖的运行时已安装,并了解
WebView2Loader.dll
的路径。 - 安装 WebView2 和 WIL - 通过 NuGet 安装
Microsoft.Web.WebView2
和Microsoft.Windows.ImplementationLibrary
,并确保packages.config
记录了所有依赖项。 - 初始化 WebView2 - 在
OnInitDialog
方法中调用CoInitialize(NULL)
并创建 WebView2 控件。 - 管理窗口大小变化 - 在
OnSize
事件中调整 WebView2 控件的Bounds
,确保窗口调整时 WebView2 能正确更新大小。 - 清理 WebView2 资源 - 在
OnDestroy
方法中调用CoUninitialize()
释放资源,避免内存泄漏。 - 加载本地或远程网页 - 使用
Navigate
加载 URL,或者NavigateToString
加载 HTML 字符串。 - 与 JavaScript 通信 - 通过
ExecuteScript
在 WebView2 中执行 JavaScript,并使用add_WebMessageReceived
监听来自 JavaScript 的消息。 - 确保必要的 DLL 存在 - 复制
WebView2Loader.dll
到应用的Debug/Release
目录,确保 WebView2 能正常运行。
通过以上步骤,可以成功在 MFC 桌面应用中集成 WebView2,并利用 WIL 进行高效的 Windows API 交互。如果在实际开发过程中遇到问题,可以参考 WebView2 官方文档或 NuGet 相关文档获取更多帮助。