qt8gt0bxhw|20009F4EEE83|RyanMain|subtext_Content|Text|0xfbfffb0000000000e100000001000300
In my last post, I outlined some ways to make the Web Browser control more useful in your C# applications, to include things such as printing and setting the text or html of the browser dynamically. That is all good, but in a typical application it does little for you if you can't interactively respond to events that occur in the document loaded in the browser control.
Last time, we looked at getting a reference to the browser's document object via the IHTMLDocument2 interface. It all starts there. Once we have a reference to the document, we can start wiring up events. Essentially what we are going to do here is setup our own application to be the receiver of the COM dispatch interop events raised by the browser's document. When we get the reference to the document via the IHTMLDocument2 interface we can wire up events, such as the document's onclick event. To do so we use the following code:
private object _empty = System.Reflection.Missing.Value;
private IHTMLDocument2 _doc;
public MainForm()
{
//navigate to about:blank to create the document
axWebBrowser1.Navigate("about:blank", ref _empty, ref _empty, ref _empty, ref _empty);
_doc = axWebBrowser1.Document as IHTMLDocument2;
//wait for document to load
while (_doc.body == null) Application.DoEvents();
//write the HTML to the document's body
_doc.body.innerHTML = "<form id=\"MainForm\">This is some text.<br><br>" +
"<input type=button id=\"btnTest1\" value=\"Button #1\"> " +
"<input type=button id=\"btnTest2\" value=\"Button #2\"></form>";
//wire up our form as the IDispatch object to receive click events
_doc.onclick = this;
}
So what have we done here? It all starts out with the things we looked at last time. We navigate to about:blank to create a document in the browser, then we write some HTML to it which includes a couple of input (type=button) tags for some buttons. Then we set 'this', or our form instance, as the IDispatch interface object to be invoked when an 'onclick' event occurs. We still need to define the default IDispatch method that will be invoked. Let's move on to that now.
When the document's event is raised it will attempt to invoke the default IDispatch method of the event receiver. We can specify which event in our code is the default method with the DispId attribute using an index of zero. Like this:
using System.Runtime.InteropServices;
//...
[DispId(0)]
public void DispatchDefault()
{
//...
}
Now our DispatchDefault method will be invoked whenever the onclick event is raised by the document. It doesn't matter what we call it, as long as it has the correct attribute and takes no arguments. But, we've wired the document's onclick event to our form. How will we know which button was clicked and raised the event? We can use the document's parent window, which is raising our events to find out the source of the event as well as which event has occurred. Take a look at the following to complete the picture:
[DispId(0)]
public void DispatchDefault()
{
HTMLWindow2 win = (HTMLWindow2)_doc.parentWindow;
string eventtype = win.@event.type;
string elementid = win.@event.srcElement.id;
switch (elementid)
{
case "btnTest1":
if (eventtype.Equals("click")) MessageBox.Show("Button #1 was clicked.");
break;
case "btnTest2":
if (eventtype.Equals("click")) MessageBox.Show("Button #2 was clicked.");
break;
}
}
If we wanted to wire up other events, such as the mouseover event, we would just wire it up and look for that event in the DispatchDefault method. You can take a look at the code above in a sample project I've included below.