我在此提供两个类可以直接完成他们的交互
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需要的功能函数。
新加完整,可以下面为准
public class InternalWeb
{
private string root = "";
private WebView2 webView;
private string name;
private object bridge;
/// <summary>
/// 桥
/// </summary>
/// <param name="web">WebView2</param>
/// <param name="webRootPath">网页根目录</param>
/// <param name="bridgeName">桥接名称</param>
/// <param name="bridgeClass">桥接类</param>
public InternalWeb(WebView2 web,string webFilePath,string bridgeName,object bridgeClass) { bridge = bridgeClass; name = bridgeName; webView = web;root = webFilePath; InitializeAsync(); }
private async void InitializeAsync()
{
try
{
var env = await CoreWebView2Environment.CreateAsync();
webView.CoreWebView2InitializationCompleted += WebView_CoreWebView2InitializationCompleted;
await webView.EnsureCoreWebView2Async(env);
if (!File.Exists(root)) { MessageBox.Show("找不到网页文件:" + root); }
webView.Source = new Uri(root);
}
catch (Exception err) { MessageBox.Show($"初始化错误: {err.Message}"); }
}
private void WebView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)
{
if (e.IsSuccess)
{
webView.CoreWebView2.WebMessageReceived += CoreWebView2_WebMessageReceived;
webView.CoreWebView2.AddHostObjectToScript(name, bridge);
}
else
{
MessageBox.Show($"WebView2 初始化失败: {e.InitializationException?.Message}");
}
}
private void CoreWebView2_WebMessageReceived(object sender, CoreWebView2WebMessageReceivedEventArgs e)
{
// 接收来自网页的消息
string message = e.TryGetWebMessageAsString();
MessageBox.Show("接受来自网页的消息:"+message);
}
/// <summary>
/// 更换网页
/// </summary>
/// <param name="url">本地网页文件</param>
private List<string> funKV = new List<string>();
public void setUrl(Uri url) { webView.Source = url; funKV.Clear();}
/// <summary>
/// 向网页发送消息
/// </summary>
public void SendMessage(string info)
{
if (webView.CoreWebView2 != null)
{
webView.CoreWebView2.PostWebMessageAsString(info);
}
else
{
MessageBox.Show("WebView2 尚未初始化完成");
}
}
/// <summary>
/// 调用网页js函数可有返回值
/// </summary>
/// <param name="txtJsFunction">函数</param>
public async Task<string> RunWebFunctionAsync(string txtJsFunction)
{
if (!funKV.Contains(txtJsFunction))
{
funKV.Add(txtJsFunction);
if (webView.CoreWebView2 != null)
{
try
{
string result = await webView.CoreWebView2.ExecuteScriptAsync(txtJsFunction);
funKV.Remove(txtJsFunction);
return result;
}
catch (Exception ex)
{
MessageBox.Show($"调用 JS 函数出错: {ex.Message}\r\n");
return null;
}
}
else
{
MessageBox.Show("WebView2 尚未初始化完成");
return null;
}
}
return null;
}
/// <summary>
/// 添加桥
/// </summary>
/// <param name="_bridgeName">桥名称</param>
/// <param name="_bridgeClass">桥类</param>
public void AddObjectToScript(string _bridgeName,object _bridgeClass)
{
webView.CoreWebView2.AddHostObjectToScript(_bridgeName, _bridgeClass);
}
/// <summary>
/// 资源释放
/// </summary>
public void Dispose()
{
if (webView != null)
{
if (webView.CoreWebView2 != null)
{
webView.CoreWebView2.WebMessageReceived -= CoreWebView2_WebMessageReceived;
webView.CoreWebView2InitializationCompleted -= WebView_CoreWebView2InitializationCompleted;
}
webView.Dispose();
webView = null;
}
}
}
桥类
[ClassInterface(ClassInterfaceType.AutoDual)]//必备
[ComVisible(true)]//必备
public class Bridge
{
// JavaScript 可以调用的方法
public void ShowMessage(string message)
{
MessageBox.Show($"JavaScript 调用 C# 方法: {message}");
}
// 另一个可以被 JavaScript 调用的方法
public string GetCurrentTime()
{
//return $"应用程序信息\n产品名称: " + Application.ProductName + "\n版本: " + Application.ProductVersion + "";
return DateTime.Now.ToString();
}
}
使用方法
InternalWeb bridge =new InternalWeb(webView, "C:\\Users\\Administrator\\Desktop\\Foresee\\bin\\Debug\\InternalWeb\\index2.html", "bridge", new Bridge());
网页代码
<script>
// 接收来自 C# 的消息
window.chrome.webview.addEventListener('message', event => {
logMessage(`来自 C# 的消息: ${event.data}`);
});
// 发送消息到 C#
function sendMessageToCSharp() {
const message = document.getElementById('messageInput').value;
window.chrome.webview.postMessage(message);
logMessage(`发送到 C# 的消息: ${message}`);
}
// 调用 C# 方法
function callCSharpMethod() {
const message = "Hello from JavaScript";
window.chrome.webview.hostObjects.bridge.ShowMessage(message); //bridge这个是使用方法里面填的名称相当于c#类后面的就是函数
logMessage(`调用 C# 方法 ShowMessage("${message}")`);
}
// 调用 C# 方法并获取返回值
async function getTimeFromCSharp() {
try {
var time = await window.chrome.webview.hostObjects.bridge.GetCurrentTime();
logMessage(`调用 C# 方法 GetCurrentTime() 返回:` + time);
} catch (error) {
logMessage(`调用 C# 方法出错: ${error}`);
}
}
// 供 C# 调用的 JavaScript 函数
function jsFunction(message) {
logMessage(`C# 调用了 jsFunction("${message}")`);
return `JavaScript 收到了: ${message}`;
}
// 记录消息到日志
function logMessage(message) {
const log = document.getElementById('messageLog');
log.innerHTML += `${message}<br>`;
log.scrollTop = log.scrollHeight;
}
396

被折叠的 条评论
为什么被折叠?



