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:

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:

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:

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.

Comments

I noticed that in your example you are waiting for the document body to no longer be null to determine that the page is loaded. Why is this used instead of waiting for documentcomplete from the web browser control?

Its amazing code, i was surching for such a nice and short way of catching events. But isnt there any way to directly call a c# function from html script code. Its possible in .net 2 There you write:
<button onclick="window.external.CShFunctiont('hello')>

Its really nice.
But IF I have one variable (var1) defined in main form ...
and I want to add some validations like
say, when I click on "btntest1", i want to check value of the variable var1
and want to make decisions (in web page) according to value of var1., whether to submit the page or not???

I tried rebuilding this project by hand and I kept getting an exception on the _doc.onclick = this. After much gnashing of teeth I discovered that I had to remove the following line from the AssemblyInfo.cs to get rid of the exception.

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
//[assembly: ComVisible(false)]

public static string GetActiveWebPage() { foreach (HTMLDocument WebPage in X(Sw)) { Please Tell me what I need to catch the "WebPage" Events.. (WebPage.parentWindow.@event is always null!) I need to catch parentWindow Events! not Document Events!) Name.Add(\\Here I don't Know); } return String.Join("\n",Names.ToArray()); }What can I write to obtain current events?I need onlyto know the HTMLDocument.parentWindow.@event.type...sent to my tabs on IE7,8 etc... or from the HWND of other instances...Please Help me,I'm feeling a dummy after 10 years...Tell me I'm a stupid and that was a simple solution...Thanks so much!

public static string GetActiveWebPage(){foreach (HTMLDocument WebPage in X(Sw)){Please Tell me what I need to catchthe "WebPage" Events..(WebPage.parentWindow.@event is always null!)I need to catch parentWindow Events! not Document Events!)Name.Add(\\Here I don't Know);}return String.Join("\n",Names.ToArray());}What can I write to obtain current events?I need onlyto know the HTMLDocument.parentWindow.@event.type...sent to my tabs on IE7,8 etc... or from the HWND of other instances...Please Help me,I'm feeling a dummy after 10 years...Tell me I'm a stupid and that was a simple solution...Thanks so much!

Any solution?

I look all over the web, i just found some information about problem with multithreding & COM , ManuelResetEvent & AutoResetEvent.