0

You can't have your cake and eat it too, apparently.

I'm currently using the System.Windows.Forms.WebBrowser in my application. The program currently depends on using the GetElementsByTagName function. I use it to gather up all the elements of a certain type (either "input"s or "textarea"s), so I can sort through them and return the value of a specific one. This is the code for that function (my WebBrowser is named 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;
}

(points to note: the webpage I need to pull from is in a frame, and depending on circumstances, the element's identifying name will be either in the name or the ref attribute)

All of that works like a dream with the System.Windows.Forms.WebBrowser.

But what it is unable to do, is redirect the opening of a new window to remain in the application. Anything that opens in a new window shoots to the user's default browser, thus losing the session. This functionality can be easily fixed with the NewWindow2 event, which System.Windows.Forms.WebBrowser doesn't have.

Now forgive me for being stunned at its absence. I have but recently ditched VB6 and moved on to C# (yes VB6, apparently I am employed under a rock), and in VB6, the WebBrowser possessed both the GetElementsByTagName function and the NewWindow2 event.

The AxSHDocVw.WebBrowser has a NewWindow2 event. It would be more than happy to help me route my new windows to where I need them. The code to do this in THAT WebBrowser is (frmNewWindow being a simple form containing only another WebBrowser called web2 (Dock set to 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;
}

I am unable to produce on my own a way to replicate that function with the underwhelming regular NewWindow event.

I am also unable to figure out how to replicate the FetchValue function I detailed above using the AxSHDocVw.WebBrowser. It appears to go about things in a totally different way and all my knowledge of how to do things is useless.

I know I'm a sick, twisted man for this bizarre fantasy of using these two things in a single application. But can you find it in your heart to help this foolish idealist?

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
friggle
  • 3,362
  • 3
  • 35
  • 47
  • Can you show us the code for how you redirect to a new page? Are you trying to reload the page in the current WebBrowser control? – Brad Rem Mar 21 '12 at 17:44
  • I currently have no code for the redirect. In the OP, the second code block is how it would work if I had NewWindow2. I wish to redirect the opening URL into a new form. – friggle Mar 21 '12 at 18:41

3 Answers3

2

I could no longer rely on the workaround, and had to abandon System.Windows.Forms.WebBrowser. I needed NewWindow2.

I eventually figured out how to accomplish what I needed with the AxWebBrowser. My original post was asking for either a solution for NewWindow2 on the System.Windows.Forms.WebBrowser, or an AxWebBrowser replacement for .GetElementsByTagName. The replacement requires about 4x as much code, but gets the job done. I thought it would be prudent to post my solution, for later Googlers with the same quandary. (also in case there's a better way to have done this)

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");
   }
}

The webbrowser.Document is cast into an IHTMLDocument2, then the IHTMLDocument2's frames are put into a IHTMLFramesCollection2, then I cast the specific desired frame into an IHTMLWindow2 (you can choose frame by index # or name), then I cast the frame's .Document member into an IHTMLDocument2 (the originally used one, for convenience sake). From there, the IHTMLDocument2's .all.tags() method is functionally identical to the old WebBrowser.Document.GetElementsByTagName() method, except it requires an IHTMLElementCollection versus an HTMLElementCollection. Then, you can foreach the collection, the individual elements needing to be IHTMLElement, and use .getAttribute to retrieve the attributes. Note that the g is lowercase.

friggle
  • 3,362
  • 3
  • 35
  • 47
0

The WebBrowser control can handle the NewWindow event so that new popup windows will be opened in the 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/

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • Sigh, I was this was sufficient. Unfortunately I'm not dealing with a straightforward HTML link. I've attempted a similar solution, but because the link is actually some Javascript, e.Cancel = true; produces an Internet Explorer Script Error, of the "Do you want to continue running scripts on this page?" Yes/No variety. – friggle Mar 21 '12 at 18:49
  • oh great, I googled around and nearly found a solution. Since I'm generating the error myself, I'd feel comfortable temporarily suppressing Javascript errors during the duration of this event. Apparently, in the AxSHDocVw.WebBrowser, there is a property called Silent that I could simply set to true......but OF COURSE, System.Windows.Forms.WebBrowser has no such property woe is me woe is me – friggle Mar 21 '12 at 18:57
  • Ah yes that would be due to the script attempting to redirect and the code canceling it. You can prevent script errors from appearing as well. http://msdn.microsoft.com/en-us/library/system.windows.forms.webbrowser.scripterrorssuppressed.aspx not sure if it will prevent those however. – Erik Philips Mar 21 '12 at 18:58
  • that works! I know its not a good practice to suppress script errors, but I've been working with this page for almost 2 years now, and I can't think of a single time when it mattered to see those errors. Oooo this is getting me there! – friggle Mar 21 '12 at 19:34
0

The only solution to this I have seen was a good few years ago now, called csExWb2, now on Google code here.

It gives you an ExWebBrowser control, but with full-on access to all the interfaces and events offered by IE. I used it to get deep and dirty control of elements in a winforms-hosted html editor.

It may be a bit of a leap jumping straight into that, mind.

Neil Moss
  • 6,598
  • 2
  • 26
  • 42