然后在一次偶然的机会发现,这个iChat的聊天室页面上9个左右的frame中,恰恰只有访问第一个frame(好象是个广告链接)会出错,而这个frame对我来说毫无用处。这下好办了,跳过第一个frame操作其它的就行了(刚刚注意到第一个frame的内容是来自另一个站点的广告页,这样如果把这个广告站点加入信任域也许就不会出错了)。随即又遇到了另外一个问题,在对页面内某frame处理时,需要判断页面是否已全部装入。之前已经发现了DocumentCompleted事件在装入多frame页面中会触发多次,但是没有办法判断来源于哪一个frame。此事件的sender参数似乎一直是顶层frame页面的这个WebBrowser。尝试用ReadyState状态来判断整个页面装入完成否,结果ReadyState值一直是InterActive,甚至在页面装入很久之后单独打印出来的状态也是InterActive,但是对没有frame的页面状态响应却很正常。再试试用每个页面的触发次数总数来判断是否整个页面的frame已经全部装入。结果发现这种方法不但繁琐而且非常不可靠。此时我是假定每个frame的文档都会触发一个DocumnetCompleted事件的,然而测试中却并非如此。
有个叫科蓝泡分机器人的软件,也是针对iChat聊天室的(其实它是个聊天室自动发广告的工具)。不知道它这里是怎么做的,因为它出现的比较早,可以假设用的是较早版本的控件,或者是用C++编写的。C++的处理手段要比C#更灵活,C#要怎么办呢?
下午在MSDN中查到了一篇最后修改于2004/7/1的文章(KB180366)对WebBrowser中的frame作了比较详细的描述,只是大约是针对旧版的WebBorwser控件的。里面提到了:
1 无frame页面装入时DocumentCompleted仅触发一次。
2 多frame页面中会触发多次,然而并非每个frame都会触发一次,而是只有触发了DownloadBegin事件的才会触发DocumentCompleted事件。
3 事件有 IDispatch*参数,可用于事件来源的判断。可能是旧版的控件参数,没有继续研究。
4 这一点比较重要,顶层frame窗口最后触发DocumentCompleted事件,也就是说整个页面装入完成也有一个事件并且是最后触发的。
.Net2.0的C#中的DocumentCompleted事件并没有IDispatch*参数,仅有sender和WebBrowserDocumentCompletedEventArgs参数。之前只把注意力放在了sender上面去了,结果每个事件的sender毫无区别。能否从WebBrowserDocumentCompletedEventArgs参数里面找出来点儿区别呢?在触发事件时打印e.Url的值,结果发现各不相同。大致是那个广告frame有一个Url,其余frame的Url为blank,而最后的Url为带聊天室用户名和密码的一长串值。测试中这个消息框每次也出现在最后,证明了是可以用它来判断全部frame装入的。
也许这不是最好的方法,但是已经足够解决目前的问题了。希望有经验的朋友能提出来更标准的解决方案。
6月5日补充: 上文中的顶层frame的DocumentCompleted事件是MS官方的解决方案,但是在实际测试中始终无法准确触发。同时注意到文中的另一个说明,由于某frame的页面中可以装入另一个frameset,而此frameset装入完毕后,会引发事件,但是由于顶层frame并未改变(改变发生在子frame中),所以顶层frame不会产生事件。当然这种情况跟现在的问题无甚联系。此聊天室页面中有9个frame,且其中有一广告页面,加载需要较长的延时,开始怀疑是这个页面的影响,但后来发现,主聊天窗口的嫌疑最大。这个窗口接收服务器的聊天消息并显示出来,测试显示,至少对这个窗口,progresschage事件比documentcompleted事件可靠。
原创文章,作者:苏葳,如需转载,请注明出处:https://www.swmemo.com/174.html