显然,你不能既有蛋糕又吃。
我目前正在我的应用程序中使用System.Windows.Forms.WebBrowser
。程序当前依赖于使用GetElementsByTagName
函数。我用它来收集特定类型的所有元素("input"或"textarea"),这样我就可以对它们进行排序并返回特定元素的值。这是该函数的代码(我的WebBrowser名为web1):
// returns the value from a element.
public String FetchValue(String strTagType, String strName)
{
HtmlElementCollection elems;
HtmlDocument page = web1.Document.Window.Frames[1].Document;
elems = page.GetElementsByTagName(strTagType);
foreach (HtmlElement elem in elems)
{
if (elem.GetAttribute("name") == strName ||
elem.GetAttribute("ref") == strName)
{
if (elem.GetAttribute("value") != null)
{
return elem.GetAttribute("value");
}
}
}
return null;
}
(需要注意的是:我需要从中提取的网页在一个框架中,根据情况,元素的识别名称将在名称或ref属性中)
所有这些对System.Windows.Forms.WebBrowser
来说就像一场梦。
但它不能做的是重定向打开一个新窗口以保留在应用程序中。在新窗口中打开的任何内容都会射向用户的默认浏览器,从而丢失会话。使用NewWindow2
事件可以很容易地修复此功能,而System.Windows.Forms.WebBrowser
没有此功能。
现在请原谅我对它的缺席感到震惊。我最近放弃了VB6,转而使用C#(是的,VB6,显然我是在岩石下工作的),在VB6中,WebBrowser
同时具有GetElementsByTagName
功能和NewWindow2
事件。
AxSHDocVw.WebBrowser
具有一个NewWindow2
事件。如果能帮我把新窗户送到我需要的地方,我会非常高兴。在该WebBrowser
中执行此操作的代码是(frmNewWindow是一个简单的表单,只包含另一个名为web2的WebBrowser
(Dock设置为Fill)):
private void web1_NewWindow2(
object sender,
AxSHDocVw.DWebBrowserEvents2_NewWindow2Event e)
{
frmNewWindow frmNW = new frmNewWindow();
e.ppDisp = frmNW.web2.Application;
frmNW.web2.RegisterAsBrowser = true;
frmNW.Visible = true;
}
我无法通过常规的NewWindow活动来复制这种功能。
我也不知道如何使用AxSHDocVw.WebBrowser
复制我上面详细介绍的FetchValue
功能。它似乎以一种完全不同的方式做事,我所有关于如何做事的知识都是无用的。
我知道我是一个病态、扭曲的人,因为我幻想在一个应用程序中使用这两种东西。但你能在心里找到帮助这个愚蠢的理想主义者的方法吗?
我再也不能依赖解决方法了,不得不放弃System.Windows.Forms.WebBrowser。我需要NewWindow2。
我最终想出了如何使用AxWebBrowser来完成我需要的东西。我最初的帖子要求为System.Windows.Forms.WebBrowser上的NewWindow2提供解决方案,或者为.GetElementsByTagName提供AxWebBrowser替代方案。该替代方案需要大约4倍的代码,但可以完成任务。我认为发布我的解决方案是明智的,因为后来谷歌员工也有同样的困惑。(还有一种更好的方法)
IHTMLDocument2 webpage = (IHTMLDocument2)webbrowser.Document;
IHTMLFramesCollection2 allframes = webpage.frames;
IHTMLWindow2 targetframe = (IHTMLWindow2)allframes.item("name of target frame");
webpage = (IHTMLDocument2)targetframe.document;
IHTMLElementCollection elements = webpage.all.tags("target tagtype");
foreach (IHTMLElement element in elements)
{
if (elem.getAttribute("name") == strTargetElementName)
{
return element.getAttribute("value");
}
}
网络浏览器。Document被转换为IHTMLDocument2,然后IHTMLDocument2中的框架被放入IHTMLFramesCollection2,然后我将特定的所需框架转换为IHTMLWindow2(您可以通过索引#或名称选择框架),然后我把框架的.Document成员转换为IHTMLDocument2(为了方便起见,最初使用的框架)。从那里,IHTMLDocument2的.all.tags()方法在功能上与旧的WebBrowser.Document.GetElementsByTagName()方法相同,只是它需要IHTMLElementCollection而不是HTMLElementCollection。然后,您可以foreach集合,单个元素需要是IHTMLElement,并使用.getAttribute来检索属性。请注意,g是小写的。
WebBrowser控件可以处理NewWindow事件,以便在WebBrowser中打开新的弹出窗口。
private void webBrowser1_NewWindow(object sender, CancelEventArgs e)
{
// navigate current window to the url
webBrowser1.Navigate(webBrowser1.StatusText);
// cancel the new window opening
e.Cancel = true;
}
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/361b6655-3145-4371-b92c-051c223518f2/
我看到的唯一解决方案是几年前的一个好方案,名为csExWb2,现在在谷歌代码上。
它为您提供了一个ExWebBrowser控件,但可以完全访问IE提供的所有接口和事件。我用它在winforms托管的html编辑器中对元素进行深入而肮脏的控制。
记住,直接跳进去可能有点跳跃。