5,665,355 members and growing! (16,440 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » .NET Framework » How To     Intermediate License: The Code Project Open License (CPOL)

Handling HTML Events from .NET, using C#

By Sharon Salmon

This article demonstrates a simple way to bind to any HTML document event from a .NET WinForms application or a BandObject or a Browser Helper Object.
C#, .NET, WinForms

Posted: 2 May 2008
Updated: 2 May 2008
Views: 8,466
Bookmarked: 27 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
15 votes for this Article.
Popularity: 5.34 Rating: 4.54 out of 5
1 vote, 6.7%
1
0 votes, 0.0%
2
1 vote, 6.7%
3
2 votes, 13.3%
4
11 votes, 73.3%
5

HtmlEventsSmple

Preface

I am not a native English speaker, and I am not heading for the Pulitzer Prize of Journalism. So, if anyone fine this “article” a bit short, get patient. My purpose here is to provide the most useful information with not too much talking. Besides, my C# English is fine enough for the VS2005 compiler :-). I hope the readers of this article will get their answer to the subject they Googled for: "Handling HTML events in .NET".

Background

I was looking for a way to handle HTML events with the .NET EventHandler. While writing my Password Management Toolbar, I needed a way to hook to the “onsubmit” event of the HTML document form in order to check the login information.

Anyway, I looked for forums and threads that would give me a straight answer, but didn’t find any. So, that left me no choice but to go to the last resort: the Reflector (Luts Roeder’s .NET Reflector).

What did I look for? When working with the WebBrowser control, you get the HtmlElement wrapper class that allows you to bind to mouse events pretty easily (like the HtmlElement.Click event). But, I do not work with the WebBrowser control, BandObject (this is the toolbar object), or the Browser Helper Object (BHO) which only have access to the MSHTML DOM elements. Also, the managed wrapper do not provide an event for “onsubmit”, so even the WebBrowser control wouldn’t do for me. So, I started digging with the Reflector to see what the guys in Microsoft did to allow binding to mouse events. The main thing that I found was the HtmlToClrEventProxy class which provided the correct interface for the object needed by the IHTMLElement2.attachEvent method. Anyway, this class is internal, so I took most of it, refined it, and made a similar public version of it that allows .NET users to easily attach to any HTMLElement event.

Using the code

The best way is to download and try the sample first. There is only one class you need to add to your project, this is the HtmlEventProxy class. This class have a factory method Create() which will do all the binding. Then, when you want to detach from the event, simply call the Detach() method of the object. The “sender” object in the EventHandler is the proxy itself. In order to get the underlying HTMLElement, use the HtmlElement property. Here are a few of the code snippets from the sample:

Let's start from the .NET event handler of the onsubmit form event. It has the regular signature of the EventHandler. The code here also extracts the form element from the sender and shows its outerHTML string.

I chose to detach from the event once it is consumed, using the Detach() method.

private void FormSubmitHabdler(object sender, EventArgs e)
{
    MessageBox.Show("form submitted");

    // show the outer html of the form
    IHTMLElement form = 
         ((HtmlEventProxy)sender).HTMLElement as IHTMLElement;
    MessageBox.Show("outer html:" + form.outerHTML);

    //detach the event from the element
    ((HtmlEventProxy)sender).Detach();
}

Now, for the code that binds the form onsubmit event to the handler:

object form = webBrowser1.Document.Forms[0].DomElement ; 
HtmlEventProxy.Create("onsubmit", form, FormSubmitHabdler);
 
object button = webBrowser1.Document.GetElementById("button1").DomElement; 
HtmlEventProxy.Create("onclick", button, ButtonClickHabdler);

First, obtain the element object from the document. Then, create a proxy with the name of the event, the DOM element, and the .NET handler.

The “HtmlEventProxy” class

The class implements the IReflect interface; that is the interface that is needed by IHTMLElement2.attachEvent(string ev,object pDisp). The most important is the implementation of the IReflect.InvokeMember method. This method detects the call to the first method entry and executes the .NET handler.

I also implemented the IDisposable interface, so the event is detached when the proxy is disposed.

public class HtmlEventProxy : IDisposable,IReflect 
{ 
 // Fields private EventHandler eventHandler; 
 private object sender; 
 private IReflect typeIReflectImplementation; 
 private IHTMLElement2 htmlElement = null; 
 private string eventName = null; 

 // private CTOR 
 private HtmlEventProxy(string eventName, IHTMLElement2 htmlElement, 
                        EventHandler eventHandler) 
 { 
   this.eventName = eventName; 
   this.htmlElement = htmlElement; 
   this.sender = this; 
   this.eventHandler = eventHandler;
   Type type = typeof(HtmlEventProxy); 
   this.typeIReflectImplementation = type; 
 }

 public static HtmlEventProxy Create(string eventName, 
               object htmlElement, EventHandler eventHandler) 
 {
   IHTMLElement2 elem = (IHTMLElement2)htmlElement; 
   HtmlEventProxy newProxy = new HtmlEventProxy(eventName,elem, eventHandler); 
   elem.attachEvent(eventName, newProxy); return newProxy; 
 }

 /// detach only once (thread safe) 
 /// 
 public void Detach() 
 { 
   lock (this)
   { 
     if (this.htmlElement != null) 
     {
       IHTMLElement2 elem = (IHTMLElement2)htmlElement; 
       elem.detachEvent(this.eventName, this);
       this.htmlElement = null; 
     } 
   } 
 } 

 /// HtmlElemet property 
 /// 
 public IHTMLElement2 HTMLElement 
 {
   get 
   { 
     return this.htmlElement; 
   } 
 } 

 #region IReflect

 ......

 object IReflect.InvokeMember(string name,BindingFlags invokeAttr, Binder binder, 
                 object target, object[] args, ParameterModifier[] modifiers, 
                 CultureInfo culture, string[] namedParameters) 
 {
   if (name == "[DISPID=0]") 
   { 
     if (this.eventHandler != null) 
     {
       this.eventHandler(this.sender, EventArgs.Empty); 
     } 
   }
   return null; 
 }

#endregion 
}

You can download the latest version of HtmlEventProxy.cs from here.

Enjoy!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sharon Salmon


I have been writing code for more than 12 years in C C++ Java & C#.
Since 2004 I had been specializing in .Net C# .
ever since I discovered C# I am a big fan of it.
I live in Tel-Aviv Israel
I recently founded new software startup.
My Company site is www.logonce.com


e-mail: sharon@logonce.com

Occupation: CEO
Company: LogOnce - www.logonce.com
Location: Israel Israel

Other popular .NET Framework articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 3 of 3 (Total in Forum: 3) (Refresh)FirstPrevNext
GeneralDoes not work with onresize event on body element . Why and how to solve this issue.membereswes4:08 11 Nov '08  
Generalhow to handle html event in toolbarmemberBen Chang18:37 25 May '08  
GeneralRe: how to handle html event in toolbarmemberSharon Salmon7:12 26 May '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 2 May 2008
Editor: Chris Maunder
Copyright 2008 by Sharon Salmon
Everything else Copyright © CodeProject, 1999-2008
Web15 | Advertise on the Code Project