Click here to Skip to main content
15,867,756 members
Articles / Desktop Programming / Windows Forms
Article

Handling HTML Events from .NET, using C#

Rate me:
Please Sign up or sign in to vote.
4.88/5 (24 votes)
2 May 2008CPOL3 min read 91.9K   1.8K   65   12
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.

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.

C#
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:

C#
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.

C#
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)


Written By
CEO LogOnce - www.logonce.com
Israel Israel
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

Comments and Discussions

 
QuestionSolved my problem Pin
Sean Stryker20-Apr-17 3:09
Sean Stryker20-Apr-17 3:09 
GeneralMy vote of 5 Pin
sam0310266-May-12 10:39
sam0310266-May-12 10:39 
Thanks! Great advice! It was very useful for me!
QuestionHandling form.onSubmit if form submited by form.Submit() method in JavaScript Pin
fandm4-Oct-11 2:59
fandm4-Oct-11 2:59 
GeneralGreat Job Pin
kprakas25-May-11 3:12
kprakas25-May-11 3:12 
Questionget IE menubar, toolbar click notifications Pin
sumedh.shrikrushana16-Jul-09 0:09
sumedh.shrikrushana16-Jul-09 0:09 
QuestionIs it possible to validate the values on submit and preventing submission if the values in form are invalid ? Pin
Member 244772217-Apr-09 4:09
Member 244772217-Apr-09 4:09 
GeneralVery helpful Pin
Phil Hamer26-Mar-09 15:34
Phil Hamer26-Mar-09 15:34 
QuestionAjax request Pin
rixwan25-Mar-09 4:26
rixwan25-Mar-09 4:26 
GeneralGreat tool Pin
Schnedarek Vilmos26-Nov-08 2:45
Schnedarek Vilmos26-Nov-08 2:45 
GeneralDoes not work with onresize event on body element . Why and how to solve this issue. Pin
eswes11-Nov-08 3:08
eswes11-Nov-08 3:08 
Questionhow to handle html event in toolbar Pin
Ben Chang25-May-08 17:37
Ben Chang25-May-08 17:37 
AnswerRe: how to handle html event in toolbar Pin
Sharon Salmon26-May-08 6:12
Sharon Salmon26-May-08 6:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.