今天为了应对一个工作中遇到的场景,研究了下使用.NET中自带的WebBrowser时内部的JS代码与外部的C#代码相互调用的问题
我的操作系统为Win7旗舰版,IDE版本为VS2012,.NET版本为4.5
经过测试我得出了如下几个结论:(C#写的部分简称C,WebBrowser内的页面代码简称B)
1、C调用B的JS代码,可以传参数,可以接返回值(使用的是 )
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