此示例
WebView2APISample
演示如何使用 WebView2 控件和 WebView2 API 向 Win32 C++ 应用添加功能。
示例名称:
WebView2APISample
存储库目录:
WebView2APISample
解决方案文件:
WebView2Samples.sln
(位于父目录中,
\SampleApps\
)
解决方案资源管理器中的项目名称:
WebView2APISample
WebView2APISample
在 Win32 本机应用程序中嵌入 WebView2 控件。
此示例生成为 Win32 Visual Studio 2019 项目。 它在 WebView2 环境中使用 C++ 和 HTML/CSS/JavaScript。
WebView2APISample
展示了一系列 WebView2 事件处理程序和 API 方法,这些处理程序和 API 方法允许本机 Win32 应用程序直接与 WebView2 控件交互,反之亦然。
此示例及其解决方案文件是唯一的:它包含解决方案资源管理器中的其他示例的副本。
WebView2APISample
是使用 Microsoft Edge WebView2 控件生成的混合应用程序;也就是说,此应用结合了本机端和浏览器 Web 应用端。 请参阅
Microsoft Edge WebView2 简介
中的
混合应用方法
。
正在运行的
WebView2APISample
应用窗口显示 WebView2 SDK 版本以及 WebView2 运行时版本和路径。 提供了许多有用的菜单和菜单项:
如果这是你第一次使用 WebView,我们建议首先遵循
教程在 Win32 应用中开始使用 WebView2
,其中介绍了如何创建 WebView2 应用并演练一些基本的 WebView2 功能。 该特定教程不是从使用项目模板创建新的 Win32 项目开始的;相反,它从 WebView2Samples 存储库中的已完成项目开始,并指导你完成如何选择性地重新添加 WebView2 代码。
有关 WebView2 中的事件和 API 处理程序的详细信息,请参阅
WebView2 API 参考
。
步骤 1 - 安装 Microsoft Edge 的预览频道
接下来,请确保在支持的 OS 上安装 Microsoft Edge 的预览频道。 目前,我们建议使用最新版本的 Canary 频道。
如果尚未在单独的窗口或选项卡中安装 Microsoft Edge (Beta、Dev 或 Canary) 的预览频道,请参阅在
为 WebView2 设置开发环境
中
安装 Microsoft Edge 的预览频道
。 按照该部分中的步骤操作,然后返回到此页面并继续执行以下步骤。
步骤 2 - 安装 Visual Studio 2019
需要 Microsoft Visual Studio。 此示例不支持 Microsoft Visual Studio Code。 此存储库示例是 Visual Studio 2019 项目。
如果 Visual Studio 2019 (C++ 支持的最低要求版本) 尚未安装,请参阅在为
WebView2 设置开发环境
中的
安装 Visual Studio
。 按照该部分中的步骤安装支持 C++ 的 Visual Studio 2019,然后返回到此页面并继续执行以下步骤。
如果要使用 Visual Studio 2017,在 Visual Studio 2017 中打开解决方案后,请在“
项目属性配置”属性>“”常规>平台工具集“>中更改项目的”平台工具集
”。
若要使用 Visual Studio 2017,可能还需要在计算机上安装最新的 Windows SDK。
步骤 3 - 克隆 WebView2Samples 存储库
如果尚未执行此操作,请将
WebView2Sample
存储库克隆到本地驱动器。 在单独的窗口或选项卡中,请参阅为
WebView2
设置开发环境中的下载 WebView2 示例
存储库。 按照该部分中的步骤操作,然后返回到此页面,然后继续以下操作。
如果以前克隆过存储库,请将最新的提交拉取到存储库的本地副本。
步骤 4 - 在 Visual Studio 中打开解决方案
在本地驱动器上,在 Visual Studio 中打开
.sln
文件:
<your-repos-directory>/WebView2Samples/SampleApps/WebView2Samples.sln
<your-repos-directory>/WebView2Samples-main/SampleApps/WebView2Samples.sln
WebView2APISample
示例和项目是 win32 main示例。
与其他一些示例不同,示例存储库目录中没有包含此示例自述文件的专用
.sln
文件。 相反,
.sln
此示例的文件 (包括其他示例项目以及) 位于父目录中。
步骤 5 - 在出现提示时安装工作负载
Visual Studio 工作负载
- 如果出现提示,请安装请求的任何 Visual Studio 工作负载。 在单独的窗口或选项卡中,请参阅为
WebView2 设置开发环境
中的
安装 Visual Studio 工作负载
。 按照该部分中的步骤操作,然后返回到此页面,然后继续以下操作。
步骤 6 - 查看打开的项目
在本地驱动器上,在设置的 Visual Studio 版本(例如 Visual Studio 2019)中再次打开
WebView2Samples
解决方案:
<your-repos-directory>/WebView2Samples/SampleApps/WebView2Samples.sln
<your-repos-directory>/WebView2Samples-main/SampleApps/WebView2Samples.sln
在
“解决方案平台
”下拉列表中,选择“
x86
”、“
x64
”或“
ARM64
”。
在
“解决方案资源管理器
”中,右键单击“
WebView2APISample
”项目,然后选择“
生成
”。
若要缩放,请右键单击“ >
在新选项卡中打开图像
”。
这会生成项目文件
SampleApps/WebView2APISample/WebView2APISample.vcxproj
。
步骤 8 -) 项目运行 (调试
选择“
调试
>
启动调试
” (
F5
) 。
故障排除:如果跳过生成步骤并立即选择“
调试
>
”
(
F5
) ,可能会出现对话框“无法启动程序:找不到指定的路径”:
若要解决此问题:在
解决方案资源管理器
中,右键单击
“WebView2APISample
”项目,然后选择“
生成
”。
此时会打开
“WebView2APISample
应用”窗口:
若要缩放,请右键单击“ >
在新选项卡中打开图像
”。
使用示例应用。 请参阅
WebView2 API 示例的自述文件
,这是有关此示例中的代码的长自述文件。
在 Visual Studio 中,选择“
调试
>
停止调试
”。 Visual Studio 关闭应用。
步骤 9 - 更新预发行 WebView2 SDK
最初生成 & 后,请运行此项目,更新 WebView2 SDK,然后重新生成项目。
若要快速查看 GitHub 上示例应用的存储库副本中安装了哪个版本的 WebView2 SDK,请参阅
packages.config
。
此示例的存储库版本已安装 WebView2 SDK 的预发行版本。 下面,你将它更新到 WebView2 SDK 的最新预发行版本,或确认已安装最新的 SDK。 使用预发行 SDK 可以访问最新功能。
检查并更新已安装的 NuGet 包,如下所示:
在 解决方案资源管理器中,右键单击
WebView2APISample
项目 (而不是其上方) 的解决方案节点,然后选择“
管理 NuGet 包
”。
“NuGet 包管理器
”面板在 Visual Studio 中打开。
在搜索文本框右侧,选择“
包括预发行
检查”框。
在
NuGet 包管理器
中,单击“
已安装
”选项卡。在每个包的右侧,检查是否列出了更新的版本号以及现有的版本号。
单击“
更新
”选项卡。如果更新可用于 WebView2 或 WIL 包,如果需要,可以在此处更新包。
在右侧的
“版本
”下拉列表中,如果希望能够尝试最新的 API,请确保选择了“
最新预发行版
”:
上图来自另一个项目,但类似。 若要缩放,请右键单击“ >
在新选项卡中打开图像
”。
单击“
更新
”按钮。
此时将显示
“预览更改
”对话框:
上图来自另一个项目,但类似。
单击“
确定”
按钮。
现已为此项目安装最新版本的 WebView2 SDK。
步骤 10 - 使用更新的 SDK 生成并运行项目
在
“解决方案资源管理器
”中,右键单击“
WebView2APISample
”项目,然后选择“
生成
”。
选择“
调试
>
启动调试
” (
F5
) 。
此时会打开
“WebView2APISample
应用”窗口:
使用示例应用。
在 Visual Studio 中,选择“
调试
>
停止调试
”。 Visual Studio 关闭应用。
步骤 11 - 检查代码
在 Visual Studio 代码编辑器中,根据以下部分检查代码。
应用程序体系结构
API 示例应用是混合应用程序的示例。 它有两个部分:Win32 本机部件和 WebView 部件。
Win32 部件可以访问本机 Windows API。
WebView 容器可以利用标准 Web 技术 (HTML、CSS、JavaScript) 。
这种混合方法允许使用 Web 技术更快地创建和迭代,同时仍能够利用本机功能。 示例应用专门演示了这两个组件如何相互交互。
示例应用的这两个部分都显示在下图中:
第一部分:示例应用的顶部是用 C++ 编写的 Win32 组件。 应用程序的这一部分接收来自用户的 UI 输入,并使用这些输入来控制 WebView。
第二部分:示例应用的main部分是一个 WebView,可以使用标准 Web 技术 (HTML/CSS/JavaScript) 重新调整用途。 可以导航到网站或本地内容。
本部分简要介绍存储库中的一些关键文件。 WebView2APISample 垂直划分为多个组件,而不是水平划分为层。 每个组件实现一类示例功能的整个工作流,从侦听菜单命令到调用 WebView API 方法来实现它们。
1. App.cpp
这是运行示例应用的顶级文件。 它读取命令行选项、设置进程环境并处理应用的线程模型。
2. AppWindow.cpp
此文件实现应用程序窗口。 在此文件中,我们首先设置所有 Win32 控件。 其次,我们初始化 WebView 环境和 WebView。 第三,我们将一些事件处理程序添加到 WebView,并创建处理应用程序的各种功能的所有组件。 类
AppWindow
本身处理应用程序的“窗口”菜单中的命令。
3. FileComponent.cpp
此组件处理“文件”菜单 (命令,退出) 除外,以及
DocumentTitleChanged
事件。
4. ScriptComponent.cpp
此组件处理“脚本”菜单中的命令,这些命令涉及通过注入 JavaScript、发布 WebMessages、将本机对象添加到网页或使用 DevTools 协议与网页通信来与 WebView 交互。
5. ProcessComponent.cpp
此组件处理来自“进程”菜单的命令,这些命令涉及与浏览器进程交互。 它还处理 ProcessFailed 事件,以防浏览器进程或其呈现进程之一崩溃或无响应。
6. SettingsComponent.cpp
此组件处理“设置”菜单中的命令,并且还负责在创建新 WebView 时从旧 WebView 复制设置。 可以在此处找到与 接口交互的
ICoreWebView2Settings
大多数代码。
7. ViewComponent.cpp
此组件处理“视图”菜单中的命令,以及与 WebView 的大小和可见性相关的任何功能。 当应用窗口调整大小、最小化或还原时,
ViewComponent
将调整、隐藏或显示 WebView 作为响应。 它还响应事件
ZoomFactorChanged
。
8. ScenarioWebMessage.cpp 和 ScenarioWebMessage.html
选择“方案/Web 消息”菜单项时会创建此组件。 它通过 C++ 部件和 HTML+JavaScript 部件实现示例应用程序,这些部件通过异步发布和接收消息相互通信。
9. ScenarioAddHostObject.cpp 和 ScenarioAddHostObject.html
选择“方案/主机对象”菜单项时,将创建此组件。 它通过主机对象注入演示本机应用与 HTML 网页之间的通信。 主机对象的接口在 中
HostObjectSample.idl
声明,对象本身在 中
HostObjectSampleImpl.cpp
实现。
以下部分简要介绍了示例应用中的一些关键功能。
AppWindow.cpp
InitializeWebView ()
在 AppWindow 文件中,我们使用 InitializeWebView () 函数通过
CreateCoreWebView2EnvironmentWithOptions 创建 WebView2
环境。
创建环境后,使用
CreateCoreWebView2Controller
创建 WebView。
若要查看这些 API 调用的运行情况,请参阅 中的
InitializeWebView()
以下代码片段。
HRESULT hr = CreateCoreWebView2EnvironmentWithOptions(
subFolder, nullptr, options.Get(),
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
this, &AppWindow::OnCreateEnvironmentCompleted)
.Get());
if (!SUCCEEDED(hr))
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
MessageBox(
m_mainWindow,
L"Couldn't find Edge installation. "
"Do you have a version installed that's compatible with this "
"WebView2 SDK version?",
nullptr, MB_OK);
ShowFailure(hr, L"Failed to create webview environment");
OnCreateEnvironmentCompleted ()
此回调函数在 CreateCoreWebView2EnvironmentWithOptions
中 InitializeWebView()
传递给 。 它存储了环境指针,然后使用它创建新的 WebView。
HRESULT AppWindow::OnCreateEnvironmentCompleted(
HRESULT result, ICoreWebView2Environment* environment)
CHECK_FAILURE(result);
m_webViewEnvironment = environment;
CHECK_FAILURE(m_webViewEnvironment->CreateCoreWebView2Controller(
m_mainWindow, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
this, &AppWindow::OnCreateCoreWebView2ControllerCompleted)
.Get()));
return S_OK;
OnCreateCoreWebView2ControllerCompleted ()
此回调函数在 CreateCoreWebView2Controller
中 InitializeWebView()
传递给 。 在这里,我们初始化与 WebView 相关的状态,注册一些事件处理程序,并创建应用组件。
RegisterEventHandlers ()
此函数在 中 CreateCoreWebView2Controller
调用。 它设置应用程序使用的一些事件处理程序,并将其添加到 WebView。
若要详细了解 WebView2 中的事件处理程序,可参阅此 文档。
下面是 来自 RegisterEventHandlers()
的代码片段,其中我们为 NewWindowRequested
事件设置了事件处理程序。 当网页中的 JavaScript 调用 window.open()
时会触发此事件,并且我们的处理程序会生成一个新的 AppWindow
,并将新窗口的 WebView 传递回浏览器,以便它可以从调用中 window.open()
返回它。 与调用 CreateCoreWebView2EnvironmentWithOptions
和 CreateCoreWebView2Controller
不同,我们只是提供一个 C++ lambda,而不是提供回调的方法。
CHECK_FAILURE(m_webView->add_NewWindowRequested(
Callback<ICoreWebView2NewWindowRequestedEventHandler>(
[this](
ICoreWebView2* sender,
ICoreWebView2NewWindowRequestedEventArgs* args) {
wil::com_ptr<ICoreWebView2Deferral> deferral;
CHECK_FAILURE(args->GetDeferral(&deferral));
auto newAppWindow = new AppWindow(L"");
newAppWindow->m_isPopupWindow = true;
newAppWindow->m_onWebViewFirstInitialized = [args, deferral, newAppWindow]() {
CHECK_FAILURE(args->put_NewWindow(newAppWindow->m_webView.get()));
CHECK_FAILURE(args->put_Handled(TRUE));
CHECK_FAILURE(deferral->Complete());
return S_OK;
.Get(),
nullptr));
ScenarioWebMessage
这些文件 ScenarioWebMessage
显示 Win32 主机如何修改 WebView、WebView 如何修改 Win32Host,以及 WebView 如何通过访问 Win32 主机的信息来修改自身。 这是异步完成的。
以下部分演示了每个离散函数如何使用示例应用工作,然后说明如何实现此功能。
首先,使用以下步骤导航到示例应用中的 ScenarioWebMessage 应用程序:
打开示例应用
单击“方案”
单击“Web 消息传送”
WebView 应显示标题为“WebMessage 示例页”的简单网页。 可以在 文件中找到 ScenarioWebMessage.html
此页的代码。
若要更好地了解 ScenarioWebMessage 功能,可以按照页面上的说明或下面详述的步骤进行操作。
1. 将消息 (Win32 主机发布到 WebView)
以下步骤演示了 Win32 主机如何修改 WebView。 在此示例中,会将文本变为蓝色:
单击工具栏中的“脚本”
单击“发布 Web 消息 JSON”
应显示包含预编写代码 {"SetColor":"blue"}
的对话框。
单击“确定”
“发布消息”下的文本现在应为蓝色。
以下是相应的工作方式:
在 ScriptComponent.cpp
中,我们使用 PostWebMessageAsJson 将用户输入发布到 ScenarioMessage.html
Web 应用程序。
// Prompt the user for some JSON and then post it as a web message.
void ScriptComponent::SendJsonWebMessage()
TextInputDialog dialog(
m_appWindow->GetMainWindow(),
L"Post Web Message JSON",
L"Web message JSON:",
L"Enter the web message as JSON.",
L"{\"SetColor\":\"blue\"}");
if (dialog.confirmed)
m_webView->PostWebMessageAsJson(dialog.input.c_str());
在 Web 应用程序中,事件侦听器用于接收和响应 Web 消息。 下面的代码片段来自 ScenarioWebMessage.html
。 如果事件侦听器读取“SetColor”,则会更改文本的颜色。
window.chrome.webview.addEventListener('message', arg => {
if ("SetColor" in arg.data) {
document.getElementById("colorable").style.color = arg.data.SetColor;
2. (WebView 接收消息到 Win32 主机)
以下步骤演示 WebView 如何通过更改 Win32 应用的标题来修改 Win32 主机应用:
找到示例应用的标题 - 窗口左上角旁边的图标。
在“接收邮件”部分下,使用所选的新标题填写表单。
单击“发送”
找到示例应用的标题,它应该已更改为刚刚输入的标题。
以下是相应的工作方式:
在 中 ScenarioWebMessage.html
,我们调用 window.chrome.webview.postMessage () 将用户输入发送到主机应用程序。 请参阅下面的代码片段:
function SetTitleText() {
let titleText = document.getElementById("title-text");
window.chrome.webview.postMessage(`SetTitleText ${titleText.value}`);
在 中 ScenarioWebMessage.cpp
,我们使用 add_WebMessageReceived 来注册事件处理程序。 收到事件后,验证输入后,将更改应用窗口的标题。
// Setup the web message received event handler before navigating to
// ensure we don't miss any messages.
CHECK_FAILURE(m_webview->add_WebMessageReceived(
Microsoft::WRL::Callback<ICoreWebView2WebMessageReceivedEventHandler>(
[this](ICoreWebView2* sender, ICoreWebView2WebMessageReceivedEventArgs* args)
wil::unique_cotaskmem_string uri;
CHECK_FAILURE(args->get_Source(&uri));
// Always validate that the origin of the message is what you expect.
if (uri.get() != m_sampleUri)
return S_OK;
wil::unique_cotaskmem_string messageRaw;
CHECK_FAILURE(args->TryGetWebMessageAsString(&messageRaw));
std::wstring message = messageRaw.get();
if (message.compare(0, 13, L"SetTitleText ") == 0)
m_appWindow->SetTitleText(message.substr(13).c_str());
return S_OK;
}).Get(), &m_webMessageReceivedToken));
3. 往返 (WebView 到 WebView)
以下步骤演示 WebView 如何从 Win32 主机获取信息并通过显示 Win32 应用的大小来修改自身。
在 RoundTrip 下,单击“GetWindowBounds”
按钮下方的框应显示示例应用的边界。
以下是相应的工作方式:
单击“获取窗口边界”按钮时, GetWindowBounds
将调用 中的 ScenarioWebMessage.html
函数。 它使用 window.chrome.webview.postMessage () 向主机应用程序发送消息。
function GetWindowBounds() {
window.chrome.webview.postMessage("GetWindowBounds");
在 中 ScenarioWebMessage.cpp
,我们使用 add_WebMessageReceived 来注册收到的事件处理程序。 验证输入后,事件处理程序从应用窗口获取窗口边界。 PostWebMessageAsJson 将边界发送到 Web 应用程序。
if (message.compare(L"GetWindowBounds") == 0)
RECT bounds = m_appWindow->GetWindowBounds();
std::wstring reply =
L"{\"WindowBounds\":\"Left:" + std::to_wstring(bounds.left)
+ L"\\nTop:" + std::to_wstring(bounds.top)
+ L"\\nRight:" + std::to_wstring(bounds.right)
+ L"\\nBottom:" + std::to_wstring(bounds.bottom)
+ L"\"}";
CHECK_FAILURE(sender->PostWebMessageAsJson(reply.c_str()));
在 中 ScenarioWebMessage.html
,事件侦听器响应 WindowBounds 消息并显示窗口的边界:
window.chrome.webview.addEventListener('message', arg => {
if ("WindowBounds" in arg.data) {
document.getElementById("window-bounds").value = arg.data.WindowBounds;
WebView2 API 参考
Win32 应用中的 WebView2 入门