随心所欲

做个幸福的人
posts - 146, comments - 1380, trackbacks - 25, articles - 0
  博客园 :: 首页 :: 新随笔 ::  :: 订阅 订阅 :: 管理

WebBrowser控件应用:弹出新窗体和关闭窗口

Posted on 2007-04-14 18:50 随心所欲 阅读(7503) 评论(8)  编辑 收藏 所属分类: VS2005

 

缘起:上次写了一个《WebBrowser控件的简单应用2》,提到了在NewWindow事件中打开新窗口的例子。有网友“队长 提出那个事件得到的参数是本页面的,而不是新页面的,经过测试,果然url参数不是新页面的。

Open新页面要处理的:

1<<a href=’xxxxx’ target=’_blank’>>; 
     2: onclick=’window.open’ ;

3:引用js文件

4ClientScript.RegisterStartupScript();等。

5:还有要实现在打开的页面里能用window.opener对象

Close要处理的:

1onclick=’window.close ;

2:引用js文件

3ClientScript.RegisterStartupScript()等。

 

经过在网上搜索,结果并不令人满意。基本上,WebBrowser控件不提供这个(将要打开的新页面的地址)功能,只能通过其他方法。

这里介绍一下网上的一个简单的解决方案、我的一个简单方案、微软的回答、一个终极解决方法。

 

网上现在有人给出这样的一个解决方案:在_NewWindow事件通过wb_Container.StatusText来获得当前将要打开的页面。代码可以这样写:

        private void wb_Container_NewWindow(object sender, CancelEventArgs e)

        {

            e.Cancel = true;

             string newURL = wb_Container.StatusText;

            //'open

           

        }

我测试了一下,这样做基本上只能处理<a href=’xxxxx’ target=’_blank’>的这种情况。对于<button>里面的onlcick事件window.open()毫无作用。

原因很简单,他只是利用了WebBrower现实Status的特点来做,不全面,不安全。至于其他情况也是完全不能处理,比如js中使用window.Open,这个方案根本不能检查。

 

我的处理方法

刚开始,我使用了这样的思路:针对所有可能出现的情况,找个各个不同方法来处理。

比如说,对于<a herf=’’的这种情况,就用wb_Container.StatusText方法,但是要加入一个判断。If(wb_Container.StatusText!=””)。对于window.openRegisterStartupScript的,可以通过替换js来实现。

本来的window.open函数,在程序完成加载之后,我把这个函数修改成window.external.open

然后,我把我的AppBrowser类里面加入几个publicOpen函数来对应原来的jsopen函数就可以了。

这是一个代码实现。

private void wb_Container_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

        {

            //for windows.open

            if (wb_Container.DocumentText.IndexOf("window.open(") > -1 || wb_Container.DocumentText.IndexOf("window.close()") > -1)

            {

                wb_Container.DocumentText = wb_Container.DocumentText.Replace("window.open(", "window.external.open(").Replace("window.close()", "window.external.close()");

            }

        }

这样处理之后,保证了我的浏览器也能理解这些js

这个方案唯一不能处理的就是js文件里面有处理的情况。

还有一个小问题,替换之后的document对象的action变化了。这个可以通过方法来实现,就是替换上边的函数,改用递归document.all来实现,检查每个element控件的内容来实现。

但是,毕竟美中不足。

 

微软的解释是这样的:这个问题,下一个版本在解决(http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=115195),开发者可以通过扩展WebBrower及其Event来实现。并且提供了一个简单的代码(但是显示不完全)。是的,这是个好的解决方案,但不是我想要的。既然封装了这个控件,为什么不提供这么重要的一个参数呢?

 

有高手已经做出了一个模型:(http://www.codeproject.com/csharp/ExtendedWebBrowser.asp

(作者实现了一个类似IE7效果的浏览器

这个模型里面,作者自己封装并且扩展了这个控件,是个最终极的解决方法。

主要思路:提供了一个将要打开新窗口的事件,并且提供更多的参数。这些参数来自IWebBrowser2等接口,还提供了一些WndProc重载来实现window.close

下载之后,我保留了这些类,做了一个简单的测试

ExtendedWebBrowser : System.Windows.Forms.WebBrowser

   .WebBrowserExtendedEvents : UnsafeNativeMethods.DWebBrowserEvents2

   .WindowsMessages(enum)

UnsafeNativeMethods

   .DWebBrowserEvents2([ComImport, TypeLibType((short)0x1010), InterfaceType((short)2), Guid("34A715A0-6587-11D0-924A-0020AFC7AC4D")])

   .IWebBrowser2([ComImport, SuppressUnmanagedCodeSecurity, TypeLibType(TypeLibTypeFlags.FOleAutomation | (TypeLibTypeFlags.FDual | TypeLibTypeFlags.FHidden)), Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E")])

BrowserExtendedNavigatingEventArgs : CancelEventArgs

UrlContext

ScriptError

NativeMethods

结果非常不错。

主要处理的几个地方:

NewWindow2NewWindow3:处理新打开窗口

BeforeNavigate2:获得将要打开的窗口的地址。

主要提供的新事件:_StartNewWindow(object sender, BrowserExtendedNavigatingEventArgs e)

 

下边这一个是我的第二个AppBrowser类,使用上边封装扩展之后的WebBrower控件。

 

AppBrowser2 source code

Feedback

#1楼    回复  引用  查看    

2007-04-14 19:21 by 无常      
ExtendedWebBrowser 和Delphi下的 WebBrowserEx都有很多可以借鉴的代码。

#2楼 [楼主]   回复  引用  查看    

2007-04-14 19:29 by 随心所欲      
@无常
嵌入的是IE还是一个WebBrowser?可以说来听听

#3楼    回复  引用  查看    

2007-04-14 22:45 by Dflying Chen      
赞楼上的广告……

#4楼 [楼主]   回复  引用  查看    

2007-04-14 23:09 by 随心所欲      
@Dflying Chen
?

#5楼    回复  引用  查看    

2007-04-14 23:44 by gray      
我不认为window.close是如此难处理,考虑如下javascript代码
<script>
window.close = function(){alert("close")};
//...
window.close();
</script>

所以我想象中一个应该可行的思路是利用window对象所实现的IDispatchEx接口改写window.close为一个自己实现IDispatch接口Invoke方法的对象(在.NET中简单做法是声明一个dispid=0的方法)

#6楼 [楼主]   回复  引用  查看    

2007-04-16 07:48 by 随心所欲      
@gray
在我的上一篇里面提到了一个简单的解决方法。简单(简陋),可用。

#7楼    回复  引用    

2007-12-03 18:19 by 非主流 [未注册用户]
不错 谢谢~

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-04-14 19:01 编辑过
"五向定位"职业成长路线公开课(上海、南京、大连)
Google站内搜索


相关链接: