我在此提供两个类可以直接完成他们的交互
using System.Windows.Forms;
using System;
using System.Runtime.InteropServices;
using Microsoft.Web.WebView2.WinForms;
using System.Threading.Tasks;
using Microsoft.Web.WebView2.Core;
using System.IO;
using System.Text;
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class AppBridgeBase
{
public WebView2 webView;
protected string wn = "InternalWeb";
protected string wf = "index.html";
private AppBridge bridge;
protected async void InitializeAsync(AppBridge bridge)
{
try
{
this.bridge = bridge;
var env = await CoreWebView2Environment.CreateAsync(); //创建环境
await bridge.webView.EnsureCoreWebView2Async(env);//等待WebView2初始化完成
if (bridge.webView.CoreWebView2 == null)
{
MessageBox.Show("CoreWebView2初始化失败");
return;
}
RegisterAppBridge();
//加载本地内容
string htmlPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, wn, wf);
bridge.webView.CoreWebView2.Navigate(new Uri(htmlPath).AbsoluteUri);
}
catch (Exception err) { MessageBox.Show($"初始化错误: {err.Message}"); }
}
/// <summary>
/// 注册桥接对象
/// </summary>
private void RegisterAppBridge()
{
try
{
if (bridge.webView.InvokeRequired)
{
bridge.webView.Invoke((MethodInvoker)RegisterAppBridge);
return;
}
if (bridge.webView.CoreWebView2 != null)
{
try
{
bridge.webView.CoreWebView2.RemoveHostObjectFromScript("bridge");
}
catch { }
// 注册新对象
bridge.webView.CoreWebView2.AddHostObjectToScript("bridge", bridge);
// 确认注册成功
//webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("alert(\"注册成功\");");
// 订阅 WebMessageReceived 事件
bridge.webView.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
}
}
catch (Exception err)
{
MessageBox.Show($"注册桥接对象失败: {err.Message}");
}
}
private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
string message = e.TryGetWebMessageAsString();
bridge.WebMessageReceived(message);
}
/// <summary>
/// 发送信息通知
/// </summary>
public virtual async Task SendNotice(string info)
{
await webView.CoreWebView2.ExecuteScriptAsync("alert(\"来自客户端的消息:{\n" + info + "\n}\");");
}
/// <summary>
/// c#调用web中的js函数
/// </summary>
public async Task RunWebFunctionAsync(string fun)
{
await webView.CoreWebView2.ExecuteScriptAsync(fun);
}
/// <summary>
/// 接受来自网页的消息
/// </summary>
public virtual void WebMessageReceived(string message)
{
//MessageBox.Show($"接收Web消息: {message}");//监听功能,建议重载
}
/// <summary>
/// 获取版本信息
/// </summary>
public virtual string GetAppInfo()
{
return $"应用程序信息\n产品名称: " + Application.ProductName + "\n版本: " + Application.ProductVersion + "";
}
/// <summary>
/// web调用c#测试
/// </summary>
/// <param name="message">web传递的信息</param>
public virtual void TestMessage(string message) { MessageBox.Show(message, "来自JavaScript的消息"); }
/// <summary>
/// c#测试调用web
/// </summary>
/// <param name="message">传递给web的信息</param>
public virtual void TestSendMessage(string message) { RunWebFunctionAsync("test("+message+");"); }
/// <summary>
/// 创建默认路径默认网页模板
/// </summary>
public static AppBridge CreateTemplateTest(WebView2 web2)
{
Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "InternalWeb\\");
string web = @"<!DOCTYPE html>"+"\n"+
"<html lang=" + '"' + "zh-CN" + '"' + ">\n" +
"<head>\n" +
"<meta charset=" + '"' + "UTF-8" + '"' + ">\n" +
"<meta name=" + '"' + "viewport" + '"' + " content=" + '"' + "width=device-width, initial-scale=1.0" + '"' + ">\n" +
"<title>模板</title>\n" +
"<!-- <link rel=" + '"' + "stylesheet" + '"' + " href=" + '"' + "style.css" + '"' + "> -->\n" +
"</head>\n" +
"<body>\n" +
"<!-- <script src=" + '"' + "script.js" + '"' + "></script> -->\n" +
"<div id = 'butt' style = 'background-color: aquamarine;width: 100px height: 100px;' > 点击调用c#函数获取消息 </div>\n"+
"<script>\n" +
"document.getElementById('butt').addEventListener('click', async () => {\n" +
"//window.chrome.webview.postMessage('按钮点击事件');\n//向c#发送消息(c#的监听(WebMessageReceived)功能可以接收此信息)\n" +
"const info = await window.chrome.webview.hostObjects.bridge.GetAppInfo(); //如果c#函数没有返回值则不需要当成变量使用\n" +
"document.getElementById('butt').innerText = info;\n" +
" });\n" +
"function test(a){ document.getElementById('butt').innerText = a; }"+
"</script>\n" +
"</body>\n" +
"</html>\n";
if (!File.Exists(AppDomain.CurrentDomain.BaseDirectory + "InternalWeb\\index.html"))
{
File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "InternalWeb\\index.html", web, Encoding.UTF8);
}
else
{
//提示作用
MessageBox.Show(AppDomain.CurrentDomain.BaseDirectory + "InternalWeb\\index.html"+"该文件已存在,无法创建默认网页");
}
return new AppBridge(web2);
}
}
[ClassInterface(ClassInterfaceType.AutoDual)]//必须
[ComVisible(true)]//必须
// 桥接类实现
public class AppBridge:AppBridgeBase
{
/// <summary>
/// 创建链接web的桥
/// </summary>
/// <param name="web">WebView2组件</param>
/// <param name="webName">启动文件目录下的网页存放根目录</param>
/// <param name="webFile">网页文件</param>
public AppBridge(WebView2 web, string webName = "InternalWeb", string webFile = "index.html")
{
Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "InternalWeb\\");
webView = web;
wn = webName;
wf = webFile;
InitializeAsync(this);
}
/**********************下面则添加web需要调用与被调用的函数*************************/
/// <summary>
/// web调用的函数
/// </summary>
public string GetAppInfo()
{
return $"应用程序信息\n产品名称: " + Application.ProductName + "\n版本: " + Application.ProductVersion + "";
}
/// <summary>
/// c#调用web函数
/// </summary>
/// <param name="message">js函数</param>
public virtual void SendMessage(string message) { RunWebFunctionAsync("test(" + message + ");"); }
}
用此方法创建即可使用
bridge = AppBridge.CreateTemplateTest(webView);//代码中只带了相应的网页代码,或者自己创建,则可以AppBridge bridge =new AppBridge(webView);即可。
后续直接在AppBridge类里面添加web需要的功能函数。