.NET桌面程序混合开发之二:在原生WinFrom程序中使用WebView2
本文将介绍如何在WinForms中嵌入WebView2,并讲到WebView2的主要特征。点击了解更多WebView2的API。
1. 准备
- Visual Studio 2017 及以上版本
- WebView2运行时,或者安装Beta,Dev,Canary任一版本的 Microsoft Edge 预览版。受支持的操作系统有:Windows 11\10\8.1\7
- 推荐使用82.0.488.0以上的Canary(日更)版本。
2. 创建单窗体应用
创那一个只包括主窗体的桌面项目:
- 打开Visual Studio
- 依次点 文件->新建->工程
- 点 创建新的工程

- 选择 C# Windows Forms App (.NET Framework) ,然后点 Next

- 输入 工程名称 和 位置 ,在 Framework下拉列表中,选择 ** .NET Framework 4.7.2** 或以上版本

- 点 创建
3. 安装 WebView2 SDK
使用 NuGet 为工程添加 WebView2 SDK
- 在 Solution Explorer 右键点击工程名,在弹出菜单中选择 Manage NuGet Packages

- 点 Browse
- 选择 Include prerelease(包含预览版)
- 在查找框中,输入WebView2,在结果中选择 Microsoft.Web.WebView2

- 选择默认版本并点 Install

- 点 Ok
- 点 File > Save All (Ctrl+Shift+S) ,保存工程
- 点 F5 编译并运行后,程序的运行结果是一个空窗体

4. 创建一个WebView
在你的应用中添加一个WebView2控件。
- 点 Project > Add Form (Windows Forms)
- 在 Add New Item 窗口中,依次点 Visual C# Items > Web > Windows Forms > Form (Windows Forms) ,然后点 Add
- 点 View > Toolbox
- 在 Toolbox ,点开 WebView2 Windows Forms Control
注意:如果你用的是Visual Studio 2017,在Toolbox中默认是找不到WebView2控件的。若想让其显示,则需要依次选 Tools > Options > General 并且将 Automatically Populate Toolbox 设置为 true
- 把 WebView2 控件拖到 Form 窗体上。

- 在 Properties 工具框中,将 Name 属性设置为 webView。可以使用 分类- 按字母排序 来找到需要的属性

- WebView2的 Source 属性用于初始化页面的URI。将其值设置为:https://www.microsoft.com
- 点 File > Save All (Ctrl+Shift+S) 保存工程
- F5 编译运行工程
- WebView2 控件中显示如下:

注意:如果你的是高分辨率显示器,你需要为窗体应用设置置高分辨率支持
5. 添加控件及处理窗体resize事件
从Toolbox中添加更多控件,并处理窗体的resize事件。
- 点 View > Toolbox
- 在 Toolbox 点 Common Controls
- 把 TextBox 拖动到窗体上
- 在 Properties属性设置窗口,将Name 属性设置为 addressBar
- 从 Toolbox 中拖动 Button 控件到窗体上
- 在Properties属性设置窗口,将Name 属性设置为 goButton
- 将Text属性设置为 Go!
- 调整Button大小以适应文字
- 将文本框放在Button左侧,并与按钮文字对齐如下

- 重置窗体大小

- 点 View > Code 打开窗体代码文件。编写
Form_Resize函数处理窗体大小改变时,控件在恰当的位置。 - 删除如下代码
public Form1()
{
InitializeComponent();
}
- 拷贝如下代码到刚删除的代码的相同位置
public Form1()
{
InitializeComponent();
this.Resize += new System.EventHandler(this.Form_Resize);
}
private void Form_Resize(object sender, EventArgs e)
{
webView.Size = this.ClientSize - new System.Drawing.Size(webView.Location);
goButton.Left = this.ClientSize.Width - goButton.Width;
addressBar.Width = goButton.Left - addressBar.Left;
}
- 点**File > Save All (Ctrl+Shift+S) **保存工程
- F5编译运行,效果如下:

6. 地址导航
在应用中添加地址栏,让用户可以通过改变地址栏来改变WebView2展示的内容。
- 在
Form1.cs中添加CoreWebView2命名空间,代码如下:
using Microsoft.Web.WebView2.Core;
- 在窗体设计界面,双击Go按钮,以在
Form1.cs中添加goButton_Click事件响应方法,将以下代码拷到方法中:
private void goButton_Click(object sender, EventArgs e)
{
if (webView != null && webView.CoreWebView2 != null)
{
webView.CoreWebView2.Navigate(addressBar.Text);
}
}
这样,```goButton_Click```方法就实现了当用户在地址栏输入地址并点击Go按钮时,WebView2就将显示址址栏中的地址所代表的页面内容。
- 点 **File > Save All (Ctrl+Shift+S) **保存工程
- F5编译并运行
- 在地址栏中输入你想访问的地址关点Go,验证下窗口上显示的是不是你想要的内容吧。
注意:在地址栏中应输入完整的URL,如果址址不是以http://或https://开头的话,会遇到ArgumentException异常
7. Navigation(导航) 事件
在页面跳转过程中,WebView2控件会发起一系列事件。而嵌入WebView2的应用会监听到以下事件:
- NavigationStarting
- SourceChanged
- ContentLoading
- HistoryChanged
- NavigationCompleted
了解更多关于WebView2的导航事件
当一个错误发生时,会引发以下事件,可能取决于对错误网页的导航 - SourceChanged
- ContentLoading
- HistoryChanged
以下操作,将为NavigationStarting委托注册一个处理方法,处理当地址不是Https时,取消页面请求。通过此例来展示如何使用这些事件。 - 在
Form1.cs中,做如下代码更改,添加一个EnsureHttps方法
public Form1()
{
InitializeComponent();
this.Resize += new System.EventHandler(this.Form_Resize);
webView.NavigationStarting += EnsureHttps;
}
void EnsureHttps(object sender, CoreWebView2NavigationStartingEventArgs args)
{
String uri = args.Uri;
if (!uri.StartsWith("https://"))
{
args.Cancel = true;
}
}
在构造函数中,EnsureHttps被注册为WebView2控件的NavigationStarting 的事件处理方法。
- File > Save All (Ctrl+Shift+S) 保存工程
- F5 编译运行
- 如果访问HTTPS会打开正常的页面,如果是HTTP则不会正常访问
8. 脚本
主程序可以在运行时向WebView2注入JavaScript脚本。可以让WebView2运行任意的JavaScript,或者添加初始化脚本。注入的JavaScript适用于所有新的顶层文档和任何子框架,直到JavaScript被删除。注入的 JavaScript 以特定的时间运行。
- 在创建全局对象后运行注入的JavaScript。
- 在运行HTML文档中包含的任何其他脚本之前运行注入的JavaScript。
1.例如,在用户导航到非 HTTPS 站点时,添加发送警报的脚本。修改EnsureHttps函数,使用ExecuteScriptAsync方法将脚本注入到网页内容中,如下图所示
void EnsureHttps(object sender, CoreWebView2NavigationStartingEventArgs args)
{
String uri = args.Uri;
if (!uri.StartsWith("https://"))
{
webView.CoreWebView2.ExecuteScriptAsync($"alert('{uri} is not safe, try an https link')");
args.Cancel = true;
}
}
- File > Save All (Ctrl+Shift+S) 保存工程
- F5 编译运行
- 应用在访问非 HTTPS 的网站时显示警报

9. 宿主程序与页面之间的通讯
宿主程序和页面内容可以使用 postMessage 进行通信如下:
- WebView2 控件中的 Web 内容可以使用
window.chrome.webview.postMessage向宿主程序发布消息。宿主程序使用任何注册到WebMessageReceived委托方法处理消息。 - 主程序使用
CoreWebView2.PostWebMessageAsString或CoreWebView2.PostWebMessageAsJSON将消息发布到 WebView2 控件中的 Web 内容。这些消息由添加到window.chrome.webview.addEventListener的处理程序捕获。
通信机制使用原生功能将消息从 Web 内容传递到宿主程序。
在项目中,当 WebView2 控件(通过页面链接)导航到一个页面时,它会在地址栏中显示新网页的 URL 并弹出新网页的 URL。
- 在
Form1.cs文件中,更新构造函数并创建InitializeAsync函数,代码片段如下:
public Form1()
{
InitializeComponent();
this.Resize += new System.EventHandler(this.Form_Resize);
webView.NavigationStarting += EnsureHttps;
InitializeAsync();
}
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
}
在InitializeAsync 函数里,要用EnsureCoreWebView2Async awaits 调用方式,因为CoreWebView2 的初始化是异步的。
- CoreWebView2 初始化后,注册一个事件处理方法来响应
WebMessageReceived事件。在Form1.cs文件中,使用以下代码替换InitializeAsync并添加UpdateAddressBar。
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
webView.CoreWebView2.WebMessageReceived += UpdateAddressBar;
}
void UpdateAddressBar(object sender, CoreWebView2WebMessageReceivedEventArgs args)
{
String uri = args.TryGetWebMessageAsString();
addressBar.Text = uri;
webView.CoreWebView2.PostWebMessageAsString(uri);
}
为了让WebView2发送和响应web消息,
CoreWebView2初始化后,宿主程序在web内容中注入一个脚本:
a. 使用postMessage将 URL 发送到宿主程序。
b. 注册一个事件处理程序以打印从宿主程序发送的消息。在
Form1.cs文件中,用以下代码段修改InitializeAsync:
async void InitializeAsync()
{
await webView.EnsureCoreWebView2Async(null);
webView.CoreWebView2.WebMessageReceived += UpdateAddressBar;
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.postMessage(window.document.URL);");
await webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("window.chrome.webview.addEventListener(\'message\', event => alert(event.data));");
}
- File > Save All (Ctrl+Shift+S) 保存工程
- F5 编译运行
- 当通过页面链接访问到新的URI时,WebView2 控件便会将新页面地址显示到地址栏。
至此,一个 WebView2 应用就完成了。
.NET桌面程序混合开发之二:在原生WinFrom程序中使用WebView2的更多相关文章
- Android混合开发之WebViewJavascriptBridge实现JS与java安全交互
前言: 为了加快开发效率,目前公司一些功能使用H5开发,这里难免会用到Js与Java函数互相调用的问题,这个Android是提供了原生支持的,不过存在安全隐患,今天我们来学习一种安全方式来满足Js与j ...
- Android混合开发之WebView与Javascript交互
前言: 最近公司的App为了加快开发效率选择了一部分功能采用H5开发,从目前市面的大部分App来讲,大致分成Native App.Web App.Hybrid App三种方式,个人觉得目前以Hybri ...
- Android混合开发之WebView使用总结
前言: 今天修改项目中一个有关WebView使用的bug,激起了我总结WebView的动机,今天抽空做个总结. 混合开发相关博客: Android混合开发之WebView使用总结 Android混合开 ...
- ios开发之OC基础-oc小程序
本系列的文章主要来自于个人在学习前锋教育-欧阳坚老师的iOS开发教程之OC语言教学视频所做的笔记,边看视频,边记录课程知识点.建议大家先过一遍视频,在看视频的过程中记录知识点关键字,把把握重点,然后再 ...
- IOS开发之Iphone和Ipad应用程序图标和启动动画
本文转载至 http://blog.csdn.net/yesjava/article/details/8782060 当我们用xcode开发iphone和ipad应用程序的时候,我们可以用一下表中所显 ...
- Android NDK开发之从Java与C互调中详解JNI使用(一)
生活 这一个礼拜过得真的是苦不堪言,上周因为打球脚踝直接扭伤,肿的想猪蹄一样,然后休息几天消肿了,可以缓慢龟速的行走了,然而五一回来上班第一天,上班鞋子还能穿上,下班脚已插不进鞋子里面了,好吧,又肿回 ...
- iBrand 开源电商小程序 (Laravel API+ webpack + gulp + 原生小程序)
iBrand 社交电商产品正式进入开源过程中了,我们制定了详细的开源计划,目前已经发布了 V1 的版本,后续的版本也在陆续整理完善中. 各个版本功能明细如下图: 3 个版本计划在今年春节前全部完成,可 ...
- (56)Linux驱动开发之二
内核基础 1.li ...
- iOS 混合开发之 Cordova 实践
在15年时,之前公司使用 Cordova 做混合开发使用,后来公司没有用到了,现在重新记录下. Cordova (官网:http://cordova.apache.org/)简介: Apache Co ...
- 移动混合开发之android文件管理demo
框架采用cordova,android编译环境为android studio.系统为mac,cordova 环境搭建参考网址:http://cordova.apache.org/docs/en/5.0 ...
随机推荐
- 响应式系统与 React
0x1 React 的历史与应用 应用场景 前端应用开发,如 Meta.Ins.Netflix 的网页版 移动原生应用开发,如 Ins.Discord 结合 Electron 进行桌面应用开发 发展历 ...
- jenkins 持续集成和交付——安装与账户安全还有凭证(二)
前言 jenkins 整理完毕,共二十四章,逐步放出,互相交流学习.学会jenkins 只是第一步,真正的还是多写脚本,然后遇到构建过程的坑,然后解决. 正文 安装jenkins 首先是如何安装jen ...
- 重新整理数据结构与算法(c#)—— 树的节点删除[十八]
前言 你好这里的一个删除,指的是如果删除的叶子节点则直接删除,如果删除的是非叶子节点,则删除的是这颗子树. 这样删除的场景并不多,这种删除方式了解即可. 十七和十六没有放树图,把树图放一下. 正文 节 ...
- 函数计算GB镜像秒级启动:下一代软硬件架构协同优化揭秘
简介: 优化镜像加速冷启动大致分为两种做法:降低绝对延迟和降低冷启动概率.自容器镜像上线以来我们已经通过镜像加速技术,分阶段降低了绝对延迟.本文在此基础上,介绍借助函数计算下一代IaaS底座神龙裸金属 ...
- dotnet 提升 ToUpper 性能
在应用软件启动过程中,客户端应用软件是对性能敏感的.比如在解析命令行参数的时候,有时候需要进行字符串处理逻辑.一般来说命令行参数都是语言文化无关的,在需要进行全大写或全小写转换过程中,采用 ToUpp ...
- WebSocket集群分布式改造:实现多人在线聊天室
前言 书接上文,我们开始对我们的小小聊天室进行集群化改造. 上文地址: [WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebSocket) 本文内容摘要: ...
- selenium项目中遇到的问题总结
问题:在pycharm中运行用例能成功,在命令行运行提示找不到com包解决办法:添加一个PYTHONPATH的环境变量,值为工程目录的路径 当要查找的文本前后有换行时,用如下方法解决//td[cont ...
- 自动生成robot自动化测试用例
背景:java项目使用swagger管理接口,随着需求的开发接口也有增加,要从swagger界面中去查找出新增的接口是件很费时,效率很低的事情. 适用情况: java项目且适用swagger管理接口 ...
- Treap,Splay & LCT 学习笔记
从二叉搜索树到平衡树 二叉搜索树(Binary Search Tree)是一种二叉树的树形数据结构,它维护一个集合,并保证它的中序遍历按照递增顺序给出了这个集合的所有元素.由此,可以完成插入,删除,查 ...
- C#开源的两款功能强大的录屏神器
ScreenToGif ScreenToGif是一款由C#语言开发且开源的操作简单.免费的屏幕录制和GIF动画制作神器.它可以帮助用户捕捉计算机屏幕上的实时动画,并将其保存为高质量的 GIF 图像格式 ...