1、最近工作需要,学习了一下 winform 内嵌 webbrowser 控件,然后与 htm 页面中的 javascript 交互调用的技术,因此有了这篇心得。总的来说,javascript 与 winform 的 code 互相调用,和 web 开发中 javascript 与服务器端代码通过 ajax 互相调用有类似之处。下面就用三个例子来说明:一.将 WebBrowser 控件放置在 winform 中,然后,写一个 Page1.htm,内容如下:function test(message) alert(message); Button我将此 Page1.htm 显示在 WebBrowse
2、r 中看看,这个不难写,在 winform 中加上下面一句即可。webBrowser1.Url= new Uri(“C:workspaceWindowsFormsAppWindowsFormsAppPage1.htm“);然后运行,在 winform 中的 webbrowser 显示出来这个 htm 了,点按钮调用 javascript 函数,弹出 alert 提示,一切都很正常,没什么稀奇。二.如果我把 javascript 中的函数挪到 winform 的 cs 代码里,htm 页面还能调用的到吗?这有点 ajax 的味道了,在客户端的 javascript 里如何调用 webpage.a
3、spx.cs 里的代码,在 ajaxpro 那时候,是需要在 webpage.aspx.cs 的代码里注册一下本页供 ajax 使用,在函数前也要声明一下是 ajax 函数的。再说回来,如果想调用 winform 中的代码,也类似的,要给 winform 设置一下 ComVisibleAttribute(true), 并给webbrowser 控件设置一下 webBrowser1.ObjectForScripting 属性。webBrowser1.Url= new Uri(“C:workspaceWindowsFormsAppWindowsFormsAppPage1.htm“);webBrow
4、ser1.ObjectForScripting = this;其实,如果做的好,可以把这些代码专门归入一个类中,方便管理,这里就变为:webBrowser1.ObjectForScripting = new 某类()了;然后,再在 winform 里写一个函数。public void Test(String message)MessageBox.Show(message, “client code“);最后,htm 里调用时要用 window.external 前缀一下 Test 方法名。Button然后再运行,就发现,htm 里的 onclick 事件,居然能调用 winform 里的 co
5、de 了,真是神奇!完整 winform 代码如下:using System;using System.Windows.Forms;using System.Security.Permissions;namespace WindowsFormsAppPermissionSet(SecurityAction.Demand, Name = “FullTrust“)System.Runtime.InteropServices.ComVisibleAttribute(true)public partial class Form2 : Formprivate WebBrowser webBrowser1
6、 = new WebBrowser();public Form2()InitializeComponent();button1.Text = “call script code from client code“;button1.Dock = DockStyle.Top;button1.Click += new EventHandler(button1_Click);webBrowser1.Dock = DockStyle.Fill;Controls.Add(webBrowser1);Load += new EventHandler(Form2_Load);private void Form2
7、_Load(object sender, EventArgs e)webBrowser1.AllowWebBrowserDrop = false;webBrowser1.IsWebBrowserContextMenuEnabled = false;webBrowser1.WebBrowserShortcutsEnabled = false;webBrowser1.ObjectForScripting = this;webBrowser1.Url= new Uri(“C:workspaceWindowsFormsAppWindowsFormsAppPage1.htm“);public void
8、Test(String message)MessageBox.Show(message, “client code“); 总结一下,关键的 webBrowser1.ObjectForScripting 属性,ComVisibleAttribute(true)和 window.external。msdn 说 webBrowser1.ObjectForScripting 属性的作用是:获取或设置一个对象,该对象可由显示在 WebBrowser 控件中的网页所包含的脚本代码访问。使用该属性可以启用 WebBrowser 控件承载的网页与包含 WebBrowser 控件的应用程序之间的通信。使用该属性
9、可以将动态 HTML (DHTML) 代码与客户端应用程序代码集成在一起。为该属性指定的对象可作为 window.external 对象(用于主机访问的内置 DOM 对象)用于网页脚本。 可以将此属性设置为希望其公共属性和方法可用于脚本代码的任何 COM 可见的对象。可以通过使用 ComVisibleAttribute 对类进行标记使其成为 COM 可见的类。这一步也至关重要,如果不设置 ComVisibleAttribute(true),那这个程序就不能加载显示 htm 页面,因为htm 里用了 window.external.Test()方法,该方法所在的类如果不 ComVisible,就
10、无法访问到了。反过来,如果设置了 ComVisible,却不设置 webBrowser1.ObjectForScripting 属性,那代码执行时会报错:window.external 无效或找不到对象。 而缺少了 window.external,就更甭提了,因此,这三者缺一不可。 再看看这个 window.external,在常见的 javascript 书中不见踪影,但却非常有用,一个常见的应用是:引用别人的“在嵌入了浏览器的工程中,除了 IE 默认提供的外部方法之外,需要网页的脚本中能调用 c+代码,要实现这种交互,就必须实现脚本扩展。实现脚本扩展就是在程序中实现一个 IDispatch
11、 接口,通过 CHtmlView 类的OnGetExternal 虚函数返回此接口指针,这样就可以在脚本中通过 window.external.XXX(关键字 window 可以省略)来引用接口暴露的方法或属性(XXX 为方法或属性名)。“再看看在 c#中的脚本扩展,只需要 webBrowser1.ObjectForScripting 和 ComVisibleAttribute(true)简单一设置就完事了,简单吧!幸福吧!悲催吧!三.再来看一个,从 winform 的 code 里,能调用 html 页面里的 javascript 吗?Page1.htm,删掉 button,只保留 java
12、script 脚本。function test(message) alert(message); using System;using System.Windows.Forms;using System.Security.Permissions;namespace WindowsFormsAppPermissionSet(SecurityAction.Demand, Name = “FullTrust“)System.Runtime.InteropServices.ComVisibleAttribute(true)public partial class Form2 : Formprivate
13、 WebBrowser webBrowser1 = new WebBrowser();private Button button1 = new Button();public Form2()InitializeComponent();button1.Text = “call script code from client code“;button1.Dock = DockStyle.Top;button1.Click += new EventHandler(button1_Click);webBrowser1.Dock = DockStyle.Fill;Controls.Add(webBrow
14、ser1);Controls.Add(button1);Load += new EventHandler(Form2_Load);private void Form2_Load(object sender, EventArgs e)webBrowser1.AllowWebBrowserDrop = false;webBrowser1.IsWebBrowserContextMenuEnabled = false;webBrowser1.WebBrowserShortcutsEnabled = false;webBrowser1.ObjectForScripting = this;webBrows
15、er1.Url= new Uri(“C:workspaceWindowsFormsAppWindowsFormsAppPage1.htm“);private void button1_Click(object sender, EventArgs e)webBrowser1.Document.InvokeScript(“test“,new String “called from client code“ );这回关键的因素就是 webBrowser1.Document.InvokeScript 了,而webBrowser1.ObjectForScripting,ComVisible 不再需要了。HtmlDocument.InvokeScript 方法的作用是:执行在 HTML 页面中定义的动态脚本函数。至此,javascript 与 winform 的 code 就可以互相调用了,感觉和 web 开发也有些类似。这项技术叫在 javascript(DHTML)代码和客户端应用程序代码之间实现双向通信.