C# WinForm通过WebBrowser与HTML/JavaScript双向通信

橘子海
橘子海
发布时间:2026-10-13 | 3人浏览过
原创

在C# WinForm开发中,经常需要让WebBrowser控件显示的HTML页面与控制台程序进行数据交换。通过正确配置ComVisible属性和ObjectForScripting,可以实现JS调用C#函数以及C#调用JS脚本的功能。

实现原理与准备

C#与HTML之间的通信依赖于浏览器内部的ActiveX组件接口。要让C#方法能被JS调用,或者让JS能被C#调用,必须满足以下基础条件:首先,负责通信的C#类必须注册为COM可见([ComVisible(true)]);其次,WebBrowser控件需要明确指定哪个对象实例用于脚本交互。

第1步:创建支持通信的C#窗体类

首先创建一个WinForm窗体(如Form1.cs),并确保该类及其继承链上的所有关键类都具备ComVisibleAttribute。同时,将本地的HTML文件路径赋值给WebBrowser控件。

  • 目的:建立容器环境并加载目标网页。
  • 入口:窗体构造函数或Load事件。
  • 动作:初始化组件,设置webBrowser1.Url指向本地HTML文件。
  • 参数:HTML文件路径。
  • 完成状态:窗口运行时能正确渲染指定的HTML页面。
// Form1.cs 核心结构
using System.Windows.Forms;
namespace test
{
  [System.Runtime.InteropServices.ComVisibleAttribute(true)]
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
      // 1. 定位 HTML 文件
      string htmlPath = System.IO.Path.Combine(Application.StartupPath, "test1.htm");
      webBrowser1.Url = new Uri(htmlPath);
      
      // 2. 关键步骤:允许 JS 访问当前窗体对象
      webBrowser1.ObjectForScripting = this;
    }
  }
}

第2步:定义供JS调用的C#方法

在与WebBrowser绑定的类(此处为Form1本身)中定义公开方法。这些方法签名将直接映射到HTML中的JS函数名。

  • 目的:暴露逻辑供前端触发。
  • 动作:在Form1中添加MyMessageBox方法。
  • 参数:方法接收的数据类型需兼容(如string转为object[])。
  • 完成状态:在HTML中可通过window.external.MyMessageBox('msg')触发弹窗。
public partial class Form1 : Form
{
  // ... 省略其他代码 ...

  public void MyMessageBox(string message)
  {
    MessageBox.Show(message);
  }
}

第3步:编写HTML并建立JS回调

在同级目录下创建test1.htm。利用window.external对象作为桥梁调用C#方法,或使用document.InvokeScript从C#侧主动推送数据给JS。

  • 目的:构建用户界面并测试双向通道。
  • 动作:在按钮点击事件中执行window.external.方法名。
  • 注意:HTML中的链接或按钮若使用javascript:...协议,也可触发外部方法。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <script language="javascript">
      function showMessage(text) { alert(text); }
    </script>
  </head>
  <body>
    <!-- JS 直接调用 C# -->
    <button onclick="window.external.MyMessageBox('Hello from HTML')">
      调用C#弹窗
    </button>
  </body>
</html>

第4步:反向操作(C#调用JS)

当需要在后台修改前端状态时,C#端可以使用WebBrowser文档对象提供的InvokeScript方法来执行已注册的JS函数。

  • 目的:由后端驱动前端行为。
  • 动作:获取webBrowser1.Document并调用InvokeScript。
  • 参数:JS函数名及参数数组(即使无参也建议传空数组或null)。
// 在 Form1.cs 中定义一个按钮点击事件
private void button1_Click(object sender, EventArgs e)
{
    object[] args = new object[1];
    args[0] = "C# 正在调用 JavaScript";
    // 假设 HTML 中有个 alert 函数叫 messageBox
    webBrowser1.Document.InvokeScript("messageBox", args);
}

进阶架构:分离通信类

如果业务逻辑复杂,直接在窗体类中混合UI和API逻辑会导致维护困难。推荐使用独立的Class来管理暴露给COM的方法。

第5步:重构独立类并绑定

新建一个类(如WinOperationClass),标记ComVisible(true),并将需要跨语言访问的方法移入此类。随后在加载页面时,将这个新类的实例赋给ObjectForScripting。

// 独立通信类
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class WinOperationClass
{
    public void MyMessageBox1()
    {
        MessageBox.Show("来自独立类的消息");
    }
}

// 在 Form1_Load 中替换绑定
private void Form1_Load(object sender, EventArgs e)
{
    string htmlPath = System.IO.Path.Combine(Application.StartupPath, "test1.htm");
    webBrowser1.Url = new Uri(htmlPath);
    
    WinOperationClass w = new WinOperationClass();
    webBrowser1.ObjectForScripting = w;
}

此时,HTML中的调用方式变为:window.external.MyMessageBox1()。这种方式保持了代码结构的清晰,符合面向对象的设计原则。

常见问题排错

  1. 权限拒绝:确保Form1及其相关类都加了[ComVisible(true)],并且webBrowser1.ObjectForScripting指向了正确的实例对象,而非未定义的变量。
  2. 找不到方法:检查HTML中调用的JS函数名是否与C#公开的公共方法名完全一致(大小写敏感)。
  3. 跨线程调用:如果在异步任务中更新UI或WebBrowser内容,请使用Invoke回到主线程操作。

以上就是C#通过HTML调用WinForm方法的详细内容,更多关于C# WebBrowser双向通信的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表