Wednesday, November 19, 2008

Using WebBrowser To Edit Web Pages On The Fly

The WebBrowser control is more versatile than you might think it is. It can be used to alter the look and feel of specific pages, click buttons, and add text to input boxes. Here's a good example.

1. Create a new Windows Form and add a WebBrowser control to it.
2. Create and attach an event handler to the DocumentCompleted event of the WebBrowser control. Make the event handler look like this.


bool _finished = false;

 

void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

{

    if (!_finished)

    {

        HtmlElement qInput = webBrowser1.Document.GetElementsByTagName("INPUT").OfType<HtmlElement>().Where(el => el.Name == "q").FirstOrDefault();

        if (qInput != null)

        {

            qInput.SetAttribute("value", "Hello World!");

        }

 

        HtmlElement qButtonSearch = webBrowser1.Document.GetElementsByTagName("INPUT").OfType<HtmlElement>().Where(el => el.Name == "btnG").FirstOrDefault();

        if (qButtonSearch != null)

        {

            qButtonSearch.InvokeMember("click");

        }

        _finished = true;

    }

}



Now run the application. The result I received was this:



Let's walk through the code briefly:

The key lines in here are within the if statement that wraps the entire method code. First, I fetch all the elements with the tag name of INPUT, and I select only the tag named "q", which is the name of the element on the web page. The SetAttribute method will allow you to set the DOM attribute of any element in the HTML page. Knowing this, I can simply set the "value" attribute of the input to have the effect of filling in the textbox. In my example, I fill the textbox with the text "Hello World!".

The next small block uses the same general concept to find the Search button on the page, and then it calls "InvokeMember" to invoke the event attached to the control. In this situation above, I want to invoke the "click" event, so I pass the "click" string into the InvokeMember method, which kicks off the search, and ultimately redirects me to another page.

A brief warning:

Not all pages load all of their HTML at once. Some pages load in stages. This can have the effect of making some of your elements unavailable at DocumentCompleted. It may be necessary in this situation this to have some kind of Timer whose tick event kicks off the HTML actions you want to perform. Then, you can wrap all the actions in a try/catch, and stop the timer once the actions execute successfully.

This same general concept can also be used to set style on elements (try setting Style to "DISPLAY:none;" on an element, and see what happens.)