.NET中WebBrowser控件内部页面的JS代码与外部C#代码的相互调用

蹲街弑〆低调 提交于 2020-04-07 08:39:58

今天为了应对一个工作中遇到的场景,研究了下使用.NET中自带的WebBrowser时内部的JS代码与外部的C#代码相互调用的问题

我的操作系统为Win7旗舰版,IDE版本为VS2012,.NET版本为4.5

经过测试我得出了如下几个结论:(C#写的部分简称C,WebBrowser内的页面代码简称B)

1、C调用B的JS代码,可以传参数,可以接返回值

使用的是 webBrowser.Document.InvokeScript("JS中函数名", new object[] {参数列表})

2、B调用C中写的函数,可以传参数,可以接返回值

使用的是  window.external.[C#中的函数名](参数列表)

下面来说一下我是如何实现它们:

1、在C#代码中调用WebBrowser内页面的JS函数

可以通过WebBrowser控件中的Document.InvokeScript函数实现,不过要为放置WebBrowser的窗体相关类加特性:

[System.Runtime.InteropServices.ComVisible(true)]

没有这个特性,运行时会报错:

2、从WebBrowser内的JS代码中调用C#相关函数

可以通过JS代码:window.external.函数名(参数) 来调用C#中同名同参数个数的函数,但浏览器控件WebBrowser的ObjectForScripting属性,需要置成this(这个改动在Load函数中放置即可)

webBrowser.ObjectForScripting = this;

如果不加这行代码,JS代码调用C#函数时会报脚本错误:

在我写的一个DEMO程序中,我共设计了5种场景:

场景1:C#程序调用JS函数刷新网页,输出再见两字;测试目标:C#调用JS函数

场景2:C#程序调用JS函数刷新网页,输出文字为用户输入的文字;测试目标:C#调用带参数的JS函数

场景3:C#程序调用JS函数获取今日的年月日信息(yyyy-MM-dd);测试目标:C#能否正确接收JS函数返回值

场景4:JS调用C#函数,输出上面↑↑↑(指bulletin)的文字内容;测试目标:JS调用C#应用程序中带参数的函数

场景5:JS调用C#函数,将左侧输入框中的内容转大写后放到右侧输入框中;测试目标:JS调用C#应用程序中带参数的函数并接收返回值

下面放代码:

C#端程序FormMain.cs的代码如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WebBrowserJsTest
{
    [System.Runtime.InteropServices.ComVisible(true)]
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Load函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMain_Load(object sender, EventArgs e)
        {
            try
            {
                string path = Environment.CurrentDirectory + "\\WebBrowserJsTest.html";
                webBrowser.Navigate(path);
                webBrowser.ObjectForScripting = this;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        /// <summary>
        /// 测试1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn4Test1_Click(object sender, EventArgs e)
        {
            webBrowser.Document.InvokeScript("sayGoodBye", null);
        }

        /// <summary>
        /// 测试2
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn4Test2_Click(object sender, EventArgs e)
        {
            webBrowser.Document.InvokeScript("changeBulletin", new object[] { txt4Test2.Text });
        }

        /// <summary>
        /// 测试3
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn4Test3_Click(object sender, EventArgs e)
        {
            object obj = webBrowser.Document.InvokeScript("getTodaysDate", null);
            MessageBox.Show(obj.ToString());
        }

        /// <summary>
        /// 测试4
        /// </summary>
        /// <param name="word"></param>
        public void ShowBulletin(string word)
        {
            MessageBox.Show(word);
        }

        /// <summary>
        /// 测试5
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        public string ToUpper(string word)
        {
            return word.ToUpper();
        }
    }
}

我又写了另一个HTML文件,名为WebBrowserJsTest.html

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="utf-8" />
    <title></title>
  </head>
  <body>
    这是一个测试用的页面
    <hr />
      ========输出都写在这里========
      <div id="bulletin">你好</div>
    <hr />
      测试4:JS调用C#函数,输出上面↑↑↑的文字内容<br />
      测试目标:JS调用C#应用程序中带参数的函数<br />
      <input type="button" id="showBulletin" value="调用C#1" onclick="showBulletin();" />
    <hr />
      测试5:JS调用C#函数,将左侧输入框中的内容转大写后放到右侧输入框中<br />
      测试目标:JS调用C#应用程序中带参数的函数并接收返回值<br />
    <input type="text" id="inputValue"/>
    <input type="button" id="toUpper" value="调用C#2" onclick="toUpper();" />
    <input type="text" id="returnValue"/>
    <script>
      //测试1
      function sayGoodBye() {
        document.getElementById("bulletin").innerHTML = "再见";
      }
      //测试2
      function changeBulletin(word) {
        document.getElementById("bulletin").innerHTML = word;
      }
      //测试3
      function prefixInteger(num, n) {
        return (Array(n).join(0) + num).slice(-n);
      }
      function getTodaysDate() {
        var dateNow = new Date();
        var year = dateNow.getFullYear();
        var month = (dateNow.getMonth() + 1);
        var day = dateNow.getDate();
        return year + "-" + prefixInteger(month, 2) + "-" + prefixInteger(day, 2);
      }
      //测试4
      function showBulletin() {
        var word = document.getElementById("bulletin").innerHTML;
        window.external.ShowBulletin(word);
      }
      //测试5
      function toUpper() {
        var word = document.getElementById("inputValue").value;
        var ret = window.external.ToUpper(word);
        document.getElementById("returnValue").value = ret;
      }
    </script>
  </body>
</html>

写好这两段代码后,就可以开始测试这些功能了,如下图测试了按钮“调用JS3”

END

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!