<

Go Premium for a chance to win a PS4. Enter to Win

x

Handling WebBrowser DHTML events in your .Net Application

Published on
16,386 Points
6,486 Views
4 Endorsements
Last Modified:
Awarded

Introduction

When many people think of the WebBrowser control, they immediately think of a control which allows the viewing and navigation of web pages. While this is true, it's also very useful for displaying your own custom User Interface (UI). Those members that have used QuickEE will have seen it in action - it is the basis of the Question View pane.

In this article, I will explain how you can raise events from the WebBrowsers DHTML document, and have them handled by your application.  For instance, a user might click an HTML <button> object and your application program can then take action to handle that click.


Setting it up

The interaction between the DHTML and you application is handled by the Component Object Model (COM), so before you can handle the events you need to ensure the class holding your client code is COM-visible.  There are two methods for achieving this.  Make either your assembly or a class visble to COM interactions.

1. Make your [i]assembly[/i] COM-Visible

One option is to make your entire assembly visible to COM by going to the Assembly Information dialog (Project > [AppName] Properties > Application tab > Assembly Information) and ensure the "Make assembly COM-Visible" checkbox is checked:COM-Visible Assembly...OR...

2. Make the [i]class[/i] COM-Visible

The second (and recommended) method is to make just the parent class COM-visible. The parent class in most cases will be the Form's class that contains the WebBrowser control. This is done by adding the ComVisibleAttribute to the class....
<System.Runtime.InteropServices.ComVisible(True)> _
Public Class Form1
....

Open in new window

Now that you have done one of the above, you also need to inform the WebBrowser control which object will be handling the DHTML events. This is done by setting the ObjectForScripting property of the WebBrowser to the parent class. Because this property is not available at design time, you need to set it at run time, generally in the Forms Load event....
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        WebBrowser1.ObjectForScripting = Me
    End Sub

Open in new window

To make debugging of your application easier, it is recommended that you do not suppress the WebBrowser's scripting errors. This is done by ensuring the WebBrowsers ScriptErrorsSuppressed property is set to False.


Adding the Document to your WebBrowser

QuickEE uses Extensible Stylesheet Language Transformations (XSLT) to transform an XML document to HTML, however you can use whatever method you desire. For the purposes of this article, we will use simple HTML and add it to the WebBrowser control with its DocumentText property.

Before adding the HTML to the WebBrowser, it's important to know how to raise the events to be handled by your application. This is done by calling the DHTML window.external object, along with the name and arguments of the appropriate routine in your application.

Here's an example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<htm>
    <body>
        <button onclick="window.external.SimpleCall()">Call an application routine from script</button><br />
        <button onclick="window.external.ParameterCall(99, 'some text')">Call an application routine from script, with parameters</button><br />
        <br />
        <input type="text" value="Some text" id="txtTest"/><br />
        <button onclick="window.external.ReferenceCall('txtTest')">Call an application routine from script, sending an elements ID</button><br />
        <br />
        Reference the calling element<input type="checkbox" Checked="Checked" value="test" onclick="window.external.ReferenceCall2(this)"/>
    </body>
</html>

Open in new window

If your HTML is stored in a String variable, you add it to your WebBrowser control like this....
WebBrowser1.DocumentText = HTMLstring

Open in new window


Handling the Script calls in your code

Now that you have your WebBrowser set up with the right properties and a document, it's time to add the routines to your application. As mentioned earlier, the WebBrowsers parent class needs to be COM-visible. The reason for this is it will contain the routines which are called by the window.external object of the browser's DOM.

The first two calls ('SimpleCall' and 'ParameterCall') are easy to handle....
    Public Sub SimpleCall()
        MsgBox("Simple Call")
    End Sub

    Public Sub ParameterCall(ByVal i As Integer, ByVal s As String)
        MsgBox(String.Format("i = {0}, s = {1}", i, s))
    End Sub

Open in new window

Note how each of the routines has a declaration context of "Public".  That is equied to make these routines visible to COM.

The third call ('ReferenceCall') requires some special handling because it references an element within the HTML Document.  This code obtains an element object from an ID and displays its value in a message box:
    Public Sub ReferenceCall(ByVal cid As String)
        Dim c As HtmlElement = WebBrowser1.Document.GetElementById(cid)
        MsgBox(c.GetAttribute("value"))
    End Sub

Open in new window

The fourth call ('ReferenceCall2') passes the element which raised the event. It requires special handling because it passes an MSHTML object. This requires adding a reference to your project (to Microsoft.mshtml, which is located under the .Net tab of the Add Reference dialog)
    Public Sub ReferenceCall2(ByVal c As Object)
        MsgBox(CType(c, mshtml.IHTMLInputElement).checked)
    End Sub

Open in new window


Conclusion

As you can see, handling the DHTML events in your application is reasonably easy. Obviously you can do much more with this, especially with the addition of the MSHTML reference.  In QuickEE, I use this technique to provide a feature-rich UI and it's easy to do something similar in your own applications.


Full Project Code

<System.Runtime.InteropServices.ComVisible(True)> _
Public Class Form1

    Private HTMLstring As String = "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">" & _
    "<html>" & _
    "<body>" & _
    "<button onclick=""window.external.SimpleCall()"">Call an application routine from script</button><br />" & _
    "<button onclick=""window.external.ParameterCall(99, 'some text')"">Call an application routine from script, with parameters</button><br />" & _
    "<br />" & _
    "<input type=""text"" value=""Some text"" id=""txtTest""/><br />" & _
    "<button onclick=""window.external.ReferenceCall('txtTest')"">Call an application routine from script, sending an elements ID</button><br />" & _
    "<br/>" & _
    "Reference the calling element<input type=""checkbox"" Checked=""Checked"" onclick=""window.external.ReferenceCall2(this)""/>" & _
    "</body>" & _
    "</html>"

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        WebBrowser1.ObjectForScripting = Me
        WebBrowser1.ScriptErrorsSuppressed = False

        WebBrowser1.DocumentText = HTMLstring
    End Sub

    Public Sub SimpleCall()
        MsgBox("Simple Call")
    End Sub

    Public Sub ParameterCall(ByVal i As Integer, ByVal s As String)
        MsgBox(String.Format("i = {0}, s = {1}", i, s))
    End Sub

    Public Sub ReferenceCall(ByVal cid As String)
        Dim c As HtmlElement = WebBrowser1.Document.GetElementById(cid)
        MsgBox(c.GetAttribute("value"))
    End Sub
    Public Sub ReferenceCall2(ByVal c As Object)
        MsgBox(CType(c, mshtml.IHTMLInputElement).checked)
    End Sub

End Class

Open in new window

4
Comment
0 Comments

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Join & Write a Comment

Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month