代码改变世界

CorePlex开发手记:二、Winform与其中的WebBrowser控件的交互

2011-07-10 19:45  uonun  阅读(788)  评论(1编辑  收藏  举报

一年多以前,写过这么一篇文章:基于IE内核的浏览器:WebBrowser上的网页与Winform本身交互[Demo下载],其中演示了WebBrowser与其宿主Winform之间的交互,实现在WebBrowser的C/S程序中调用其网页上的Javascript函数,甚至反过来在网页的Javascript代码中调用C/S程序中的方法。

而最近在开发 CorePlex 的过程中,却无意发现,原来 WebBrowser 本身就有一个用于交互操作的成员:

image

MSDN上这样说:

使用该属性启用 WebBrowser 控件承载的网页与包含 WebBrowser 控件的应用程序之间的通信。使用该属性可以将动态 HTML (DHTML) 代码与客户端应用程序代码集成在一起。为该属性指定的对象可作为 window.external 对象(用于主机访问的内置 DOM 对象)用于网页脚本。

可以将此属性设置为希望其公共属性和方法可用于脚本代码的任何 COM 可见的对象。可以通过使用 ComVisibleAttribute 对类进行标记使其成为 COM 可见的类。

若要从客户端应用程序代码调用网页中定义的函数,请使用可从 Document 属性检索的 HtmlDocument 对象的 HtmlDocument..::.InvokeScript 方法。

既然如此,上一篇文章中“B/S调用C/S方法”一节,就显得太山寨了。而正确的使用方式,应该这样:

1. 设置宿主Form 为 Com可见:

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public partial class MainForm : Form

2. 将窗体的引用赋值给 WebBrowser.ObjectForScripting 属性

this.webBrowser1.ObjectForScripting = this;

至此,我们就可以在网页上,使用 window.external 来访问 MainForm 这个窗体实例了:

<script language="JavaScript" type="text/javascript">
    var f = window.external;

    function show() {
        // 窗体实例及其属性
        alert(f + "\n\n" + f.Text);
    }

    function set() {
        // 调用窗体实例的 Public 方法
        f.SetText("从网页设置的新标题");
    }

    function addfav() {
        window.external.addFavorite('http://www.udnz.com', 'CorePlex代码库');
    }
</script>
<input type="button" onclick="javascript:show();" 
        value='窗体实例及其属性' /><br />
<br />

<input type="button" onclick="javascript:set();" 
        value='f.SetText("从网页设置的新标题");' /><br />
<br />

由于 window.external 的改变,原本在IE中可以执行的代码, 
现在不能了,比如常用的加入收藏的代码:<br />
<input type="button" onclick="javascript:addfav();" 
        value='加入收藏' />

有了这个能力,现在你就可以发挥你的想象,让浏览器中一个简单的超链接,变身为超人,执行对 Winform 的强大操作了!不过请注意,由于你重新给 window.external 赋值了,因此通过这个成员调用的任何属性、方法,都应当是你 MainForm 中的东西,所以原来可以通过 window.external 调用的东西,就不再能调用了。

image