Handling mshtml Document Events without Mouse lockups
I’ve been working on a session I’m doing at the Dutch Conference To the Max conference for using the Web Browser control in .Net. For the most part the process of using this control is pretty straight forward – you import the ActiveX control and fire away at the browser events.
If you want to work with the document you can also import the Microsoft.mshtml library which is a 7meg monster that gives you access to the entire HTML object model and event system. For the most part it works pretty well so you can do something like this quite easily:
HTMLDocument Doc = this.Browser.Document as mshtml.HTMLDocument;
string DocBody = Doc.body.outerHTML;
You can drill into the various collections, pick up selections and modify and fire away at the document model just fine.
However, I’ve had major issues with the document events. It’s easy enough to capture the events of the document like this:
HTMLDocumentEvents2_Event DocEvents = this.Browser.Document as HTMLDocumentEvents2_Event;
if (DocEvents == null)
return false;
DocEvents.oncontextmenu += new
HTMLDocumentEvents2_oncontextmenuEventHandler(Browser_ContextMenu);
All of this event information and the constants come as part of mshtml and it works to hook up the events. However, it comes with a major side effect – when you hook an event of the document in this fashion the document itself stops responding to mouse clicks. All other operations stay live, you can still tab to different areas and other events such as status bar events fire just fine. But you cannot click for instance on one of the links (you can click the mouse on the link then press enter, but you can’t click with your mouse). Obviously this is hardly an acceptable solution.
The workaround for this bug is to create a separate Event object that handles the event and then forwards it to a custom handler directly, by passing the Web Browser control. This concept is based on the fact that all IE Document events are fired exactly same way using an IHTMLEventObj object that is passed to an event handling method. All events such as OnMouseDown, OnContextMenu, OnFocus etc. all receive such a parameter which contains information such as mouse status, screen position and a return value property that you can set.
With this knowledge it’s possible to create a generic event object that receives these events and allows you to hook up your own handlers. This is a little more work than the built-in handlers but it works and keeps your document alive.
The Event Handler class and delegate look like this:
///
/// Generic HTML DOM Event method handler.
///
public delegate void DHTMLEvent(IHTMLEventObj e);
///
/// Generic Event handler for HTML DOM objects.
/// Handles a basic event object which receives an IHTMLEventObj which
/// applies to all document events raised.
///
public class DHTMLEventHandler
{
public DHTMLEvent Handler;
HTMLDocument Document;
public DHTMLEventHandler(HTMLDocument doc)
{
this.Document=doc;
}
[DispId(0)]
public void Call()
{
Handler(Document.parentWindow.@event);
}
}
Remember that the Document reloads on every hit, so in order to use the above handler all the time you have to re-hook it everytime the page is navigated. Typically this means that these sort of handler are hooked up as part of the Browser’s DocumentComplete handler.
The following hooks up the OnContextMenu event of the Document:
// *** Always raise the ContextMenuClicked event
// *** Using Custom Event Object - No Mouse Lockups
HTMLDocument doc = this.Document as HTMLDocument ;
DHTMLEventHandler Handler = new DHTMLEventHandler( doc );
Handler.Handler += new DHTMLEvent(this.Browser_ContextMenuStandardEvent);
doc.oncontextmenu = Handler;
The handler method then looks like this:
private void Browser_ContextMenuStandardEvent(mshtml.IHTMLEventObj e)
{
MessageBox.Show("Context Menu Action (Event Object) Hooked");
e.returnValue = false;
}
Note that you can use the exact same signature and hookup code for any event of the HTML Document and any child elements in this same fashion. So if you want to capture a focus event for a DIV region inside of the document all you have to do is hook up the Element’s Onfocus event and assign the EventHandler to it the same way.
I hope this helps somebody out, because it took me quite some time to figure out this little tidbit. Actually I got a bit of help. The base idea came from an e-Book:
Programming Microsoft Internet Exporer in C# (Nikit Zykov – ebook):
http://www.amazon.com/exec/obidos/ASIN/B00007FYZP/westwindtechn-20/102-6053556-6633703
This $20 download e-book is a good read if you plan on using the browser control although it shows a very specific way of dealing with the control even though there are a number of approaches available. I simplified the code somewhat to make it more self-contained to just that small snippet above. The e-Book goes on to create a Document wrapper class that provides a bunch of common functionality.
I’m working on an article for this stuff, and I'll get that out when I get a little more time to clean up my notes.
The Voices of Reason
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
# System.NotImplementedException occurs
In the line below,
"doc.oncontextmenu = Handler;"
I get a System.NotImplementedException as follows. Do you have any idea what is going on?
System.NotImplementedException: Not implemented
at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
at mshtml.HTMLDocumentClass.set_onclick(Object )
-YK
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
Any clue how to modify your handler code to support this?
-Lance
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
K
# re: Handling mshtml Document Events without Mouse lockups
-Alger
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
Thanks in advance.
zmijasu
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
e.returnValue = false;
to
e.returnValue = true;
I'm not sure how this would affect other events, but I imagine that you could tailor the return value on a per-event-type basis.
Thanks *very* much for this blog post... it's the only thing I've found so far (from many Google searches) that solved my problem.
Cheers,
Corey
# re: Handling mshtml Document Events without Mouse lockups
By the way, this article rocks. I'll have to agree with Corey. Thanks.
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
System.InvalidCastException: No such interface supported.
Has anyony an idea howto get the Handler to work correctly!
My InternetExplorer Version is 6.0.2900...
I would like to have the Explorer opening a new Window that looks and feels like (and is)the InternetExplorer where I can capture some events.
Thank you for this article it is the only one I found in this topic.
# re: Handling mshtml Document Events without Mouse lockups
Unfortunately, in my case, when document contains iframe elements, all the events from within them are blocked.
The only event i can see is when the selection is changed to the iframe element. No further events come from iframes.
Have you possibly got any suggestions?
# re: Handling mshtml Document Events without Mouse lockups
But in your case, there is collection 'frames' which keeps references to all frame elements on current document. Window object also has property 'document' so you can switch from 'window' object to 'document' object.
In order to get events from all frame elements you should do the following:
1. Assign your event handlers to the 'document' that you get from your 'axBrowser'.
2. Then go to the 'document.parentWindow' and assign event handlers to the window object that hosts document object.
3. Step through 'document.parentWindow.frames' collection and get window objects for all frames on page.
4. Assign event handlers to the 'window.document' object and 'window' object.
5. Repeat from step 3 to 5 for every window element that you get from 'frames' collection.
This is recursive process because each frame can host HTML document that has frames and in order to get events from all frames you have to assign event handlers to every frame.
Keep in mind that you have to do this procedure AFTER page loads. (axBrowser.DocumentComplete event)
# re: Handling mshtml Document Events without Mouse lockups
Thanks.
# re: Handling mshtml Document Events without Mouse lockups
I mean I'm able to subscribe for the iframes events, but I'm still not able to catch the events
from the iframes.
Here's a piece of code i use to subscribe to the iframe events (steps 3 to 5)
I'm interested in only some of the document events, so i don't subscribe to the window events.
Of course i do call it from axBrowser.DocumentComplete event handler.
private void BindIFrameEvents (HtmlWindow2 window)
{
HtmlFramesCollection col = window.frames;
for (int i = 0; i < col.length; i++)
{
object index = i;
HtmlWindow2 win = (HtmlWindow2) col.item(ref index); // can't do otherwise
((mshtml.DispHTMLDocument)win.document).oncontextmenu = this; // let the method with [DispId(0)]
// to handle all the events
((mshtml.DispHTMLDocument)win.document).ondblclick = this;
this.BindIFrameEvents(win); // call recursively
}
}
Is there anything i do wrong there ?
# re: Handling mshtml Document Events without Mouse lockups
This is really helpful.
But i m facing the another problem.When i load the word document or excel document these hooked event doesnt work.
Is there any solution to my problem?
Thanks
# memory leak
I designed an IE band to track the click action on pages. the way of handling click event is just the method Rick showed me. It works, but I think this way could causes memory leak.
the symptom is that open a web page, and pop up new windows by clicking links in the page, so using memory increases, but it can be released by closing popup windows, only after the original page is closed, all memory could be released.
I guess the reason is the .net runtime and the COM object such as webcontrols hold reference of each other.
I don't know whether there is any good solutions.
thanks.
# re: Handling mshtml Document Events without Mouse lockups
# re: System.NotImplementedException occurs
I'm pretty sure you had your class DHTMLEventHandler as non public.
That class must be denoted "public" no matter where you put it.
I had the same problem and now it's fixed.
God bless you.
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
I am a newbie to C#.Net. Now i have todo a project that selects a dropdown listbox value and click a button. Here both of these things are placed in "iframe". As a newbie i cant able to find a solution for. So please help me. If you can please give me the full source code (from the begning of the function).
Thanks
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
But now I have a problem and haven't no idea for solve it, I explaint it.
I have a Web page and this page already have a function associated with the onsubmit...
how can I add my function at the existent, I want execute the two, the mine an the original.
Thanks in advance from Barcelona, Spain.
# re: Handling mshtml Document Events without Mouse lockups
[ComVisible(true)]
public class DHTMLEventHandler
Hooking events works but I'm not shure if this is useable since I override the default event handler. E.g. hooking into the documents onkeydown event leads to the result that no key is handled by the document itself (input fields etc.)
# re: VB.NET equivalent appears not to work ... can you see why?
Relevant code segments shown below:
'
' Generic HTML DOM Event method handler.
'
Public Delegate Sub DHTMLEvent(ByVal e As IHTMLEventObj)
'
' Generic Event handler for HTML DOM objects.
' Handles a basic event object which receives an IHTMLEventObj which
' applies to all document events raised.
'
<ComVisible(True)> _
Public Class DHTMLEventHandler
Public Handler As DHTMLEvent
Private Document As HTMLDocument
Public Sub New(ByVal doc As HTMLDocument)
MyBase.New()
Me.Document = doc
End Sub
<DispId(0)> _
Public Sub [Call]()
Handler(Document.parentWindow.event)
End Sub
End Class
Dim doc As HTMLDocument = CType(AxWebBrowser1.Document, HTMLDocument)
'
' OnKeyUp handler ...
'
Dim HandlerOnKeyUp As DHTMLEventHandler = New DHTMLEventHandler(doc)
HandlerOnKeyUp.Handler = New DHTMLEvent(AddressOf Me.DocumentEvents_onkeyup)
doc.onkeyup = HandlerOnKeyUp
'
' OnKeyUp handler ...
'
Dim HandlerOnContextMenu As DHTMLEventHandler = New DHTMLEventHandler(doc)
HandlerOnContextMenu.Handler = New DHTMLEvent(AddressOf Me.Browser_ContextMenuStandardEvent)
doc.oncontextmenu = HandlerOnContextMenu
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
but it didn't work, here is the code
Handler.Handler += new DHTMLEvent(ClickEventHandler);
doc.onclick =Handler;
plzzz reply
thanx in advance
# re: Handling mshtml Document Events without Mouse lockups
doc=(mshtml.HTMLDocument)this.axWebBrowser1.Document;
mshtml.HTMLDocumentEvents2_Event iEvent;
iEvent = (mshtml.HTMLDocumentEvents2_Event)doc;
iEvent.onclick+=new HTMLDocumentEvents2_onclickEventHandler(iEvent_onclick);
iEvent.onmouseover +=new HTMLDocumentEvents2_onmouseoverEventHandler(iEvent_onmouseover);
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
This is my code:
public delegate bool DHTMLEvent(IHTMLEventObj e);
public class DHTMLEventHandler
{
public DHTMLEvent Handler;
HTMLDocument Document;
public DHTMLEventHandler(HTMLDocument doc)
{
this.Document = doc;
}
[DispId(0)]
public void Call()
{
Handler(Document.parentWindow.@event);
}
}
HTMLDocument doc = (HTMLDocument)activeBrowserObj.Document;
DHTMLEventHandler Handler = new DHTMLEventHandler(doc);
Handler.Handler += new DHTMLEvent(ClickEventHandler);
((DispHTMLDocument)doc).onclick = Handler;
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
Imports mshtml
Public Delegate Sub DHTMLEvent(ByVal e As IHTMLEventObj)
<Runtime.InteropServices.ComVisible(True)> _
Public Class DHTMLEventHandler
Public Handler As DHTMLEvent
Private Document As HTMLDocument
Public Sub New(ByVal doc As HTMLDocument)
Me.Document = doc
End Sub
<Runtime.InteropServices.DispId(0)> _
Public Sub [Call]()
Handler(Document.parentWindow.event)
End Sub
End Class
Private Sub Browser_DownloadBegin(ByVal sender As Object, ByVal e As System.EventArgs) Handles Browser.DownloadBegin
Dim doc As HTMLDocument = CType(Browser.Document, HTMLDocument)
If doc IsNot Nothing Then
Dim Handler As DHTMLEventHandler = New DHTMLEventHandler(doc)
Handler.Handler = AddressOf Me.Browser_ContextMenuStandardEvent
' add the events in here
doc.oncontextmenu = Handler
doc.onselectionchange = Handler
End If
End Sub
Private Sub Browser_ContextMenuStandardEvent(ByVal e As mshtml.IHTMLEventObj)
MessageBox.Show(String.Format("Action (Event Object) Hooked {0}", e.type))
Select Case e.type
Case "oncontextmenu"
e.returnValue = False
Case "onselectionchange"
End Select
End Sub
# re: Handling mshtml Document Events without Mouse lockups
But it does not work in Visual Studio 2005.
Please define the class DHTMLEventHandler as ComVisilbe(true).
[ComVisible(true)]
public class DHTMLEventHandler
It works.
Thanks Rick Strahl, the way is wonderful.
# Missing Event
for first time I used this part of code:
HTMLDocument Doc = axWebBrowser1.Document as mshtml.HTMLDocument;
HTMLDocumentEvents2_Event DocEvents = axWebBrowser1.Document as HTMLDocumentEvents2_Event;
DocEvents.onmousemove += new HTMLDocumentEvents2_onmousemoveEventHandler(DocEvents_onmousemove);
then I added this code in below of it :
HTMLDocument doc = axWebBrowser1.Document as HTMLDocument;
DHTMLEventHandler Handler = new DHTMLEventHandler(doc);
Handler.Handler = new DHTMLEvent(DocEvents_onmousemove);
((DispHTMLDocument)doc).onmousemove = Handler;
I used second part of code aparently too.
I can get event but it couldn't transfare to the axWebBroser and it can't do any thing.
please help me.
thanks.
# re: Handling mshtml Document Events without Mouse lockups
You saved me, thank you!!
I was having the same problem using HTMLTextContainerEvents2
to hook up ondragenter, ondragover and ondrop events.
You code works just fine!!
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
-Dan
# re: Handling mshtml Document Events without Mouse lockups
<html>
<body>
<form>
First name:
<input type="text" name="firstname">
<br>
Last name:
<input type="text" name="lastname">
</form>
</body>
</html>
# re: Handling mshtml Document Events without Mouse lockups
Getting:
Ambiguity between 'mshtml.DispHTMLDocument.oncontextmenu' and 'mshtml.HTMLDocumentEvents_Event.oncontextmenu'
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
static SHDocVw.WebBrowser browserInstance = null;
static SHDocVw.ShellWindows shellWindows = new SHDocVw.ShellWindowsClass();
foreach (SHDocVw.WebBrowser ie in shellWindows)
{
if (ie.HWND == The IE Handle I want)
{
browserInstance = ie;
break;
}
}
I get Doc from browserInstance.
New to this...not sure what you mean by IHTML.
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
wondering how I can capture drag and drop event in the web browser control ? I can capture mouseup event but if I drag an item in then i can not get mouseup. any idea ?
thanks in advance !
# re: Handling mshtml Document Events without Mouse lockups
"COM object that has been separated from its underlying RCW cannot be used."
from the Call method, in the Handler(Document.parentWindow.@event) line
looks like the 'parentWindow' has thrown the 'InvalidCOMObjectException.
# re: Handling mshtml Document Events without Mouse lockups
doc.oncontextmenu = Handler;
However, I cast the doc to mshtml.DispHTMLDocument:
((mshtml.DispHTMLDocument)doc).oncontextmenu = Handler;
since casting it to mshtml.HTMLDocumentEvents_Event does not compile in that it expects a hook (+= or -=).
Unfortunately, my events still do not fire. I have the following...
mshtml.HTMLDocument doc = this.axWebBrowser1.Document as mshtml.HTMLDocument; DHTMLEventHandler Handler = new DHTMLEventHandler(doc); Handler.Handler += new DHTMLEvent(iEvent_onmouseup);
where the browser's document is accessed externally rather than internally (this.Document). Although I do not think that should be the problem...any help? =)
((mshtml.DispHTMLDocument)doc).oncontextmenu = Handler;
# re: Handling mshtml Document Events without Mouse lockups
doc.oncontextmenu = Handler;
However, I cast the doc to mshtml.DispHTMLDocument:
((mshtml.DispHTMLDocument)doc).oncontextmenu = Handler;
since casting it to mshtml.HTMLDocumentEvents_Event does not compile in that it expects a hook (+= or -=).
Unfortunately, my events still do not fire. I have the following...
mshtml.HTMLDocument doc = this.axWebBrowser1.Document as mshtml.HTMLDocument; DHTMLEventHandler Handler = new DHTMLEventHandler(doc); Handler.Handler += new DHTMLEvent(Browser_ContextMenuStandardEvent); ((mshtml.DispHTMLDocument)doc).oncontextmenu = Handler;
where the browser's document is accessed externally rather than internally (this.Document). Although I do not think that should be the problem...any help? =)
***Please forgive the double post, a line from the code I have wandered to the bottom of the post...somehow...do_Ob
# re: Handling mshtml Document Events without Mouse lockups
((mshtml.DispHTMLDocument)doc).oncontextmenu = Handler;
It hits the line and then breaks out of the scope...do_Ob
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
public DHTMLEventHandler(IHTMLDocument2 doc)
{
this.Document = doc;
}
// Document(or Frame) event handlers, if this is not declared, you can not catch event.
DHTMLEventHandler HandlerFrame = new DHTMLEventHandler(document);
HandlerFrame.Handler += new DHTMLEvent(this.MouseClick);
document.onclick = HandlerFrame;
this is working successfully. But another Bho overridde older onclick. Any suggestion?
# re: Handling mshtml Document Events without Mouse lockups
public delegate void DHTMLEvent(mshtml.IHTMLEventObj e); [ComVisible(true)] public class DHTMLEventHandler { public DHTMLEvent Handler; mshtml.IHTMLDocument2 Document; public DHTMLEventHandler(mshtml.IHTMLDocument2 doc) { this.Document = doc; } [DispId(0)] public void Call() { Handler(Document.parentWindow.@event); } }
Above is the code extracted from the post. I've tried both with Interfaces and the class itself.
I read all the topics and can't find a solution. It always throws an Invalid cast exception when I try to reach parentWindow.
# re: Handling mshtml Document Events without Mouse lockups
What is up?
wbInfo.Navigate(strURL)
Try
wbInfo.Refresh2()
Catch ex As Exception
' Do nothing; there is no real exception.
End Try
Dim doc As HTMLDocument = CType(wbInfo.Document, HTMLDocument)
'doc = CType(wbInfo.Document, HTMLDocument)
If Not (doc Is Nothing) Then
Dim Handler As DHTMLEventHandler = New DHTMLEventHandler(doc)
Handler.Handler = AddressOf wbInfo_DHTMLEventHandler
' add the events in here
doc.onclick = Handler
'doc.onselectionchange = Handler
End If ' Not (doc Is Nothing)
wbInfo is my browser control.
Please help, this is VERY frustrating! I tried moving the handler to NavigationComplete, DownloadComplete and DocumentComplete, but for some reason those events never get fired.
Thanks,
Jake
# re: Handling mshtml Document Events without Mouse lockups
Anyone else?
I tried it in VB & C#, but once I navigate to a 2nd page, the handler quits working.
Any ideas?
Jake
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
Thanks for the reply. I don't know what I'm doing wrong, but I put the event handler in DocumentComplete & NavigateComplete to reattach the handler, but those Events are never triggered. My code to change my page is:
wb.Navigate(strURL)
Try
wb.Refresh2()
Catch
End Try
Now, the control will NOT navigate with the .Navigate call, but after I call .Refresh2, then it will change the page, however, it's not throwing any events, and if I don't trap the Refresh2 command, it gives me a invocation exception.
I'm not sure how to get the browser to navigate properly, but this all started with the IE7 update.
Perhaps there is code, or a sample, that someone has to get a standard Ax... Browser to navigate to a page created on the local disk?
I'm fairly sure that it's this problem with my navigation that is causing me problems... If I take out the .Refresh2() call, then it will not change the page... Since the handler only works the first time around, it makes me think this is related... Would it help if I posted my code for the webbrowser??
Thanks so much for your time,
Jake
# re: Handling mshtml Document Events without Mouse lockups
public delegate void DOMEvent(mshtml.IHTMLEventObj e); public class DOMEventHandler { public DOMEvent Handler; DispHTMLDocument Document; public DOMEventHandler(DispHTMLDocument doc) { this.Document = doc; } [DispId(0)] public void Call() { Handler(Document.parentWindow.@event); } }
and then we use the handler as;
mshtml.DispHTMLDocument dispDoc = webBrowser.Document as mshtml.DispHTMLDocument; DOMEventHandler onkeydownhandler = new DOMEventHandler(dispDoc); onkeydownhandler.Handler += new DOMEvent(docEvents_onkeydown); dispDoc.onkeydown = onkeydownhandler;
# re: Handling mshtml Document Events without Mouse lockups
Finally it works!!! It was a REAL pain in the a*s!!! Thanks for the blog!!!
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
# InvalidCastException when attempting to access Document.parentWindow
Handler(Document.parentWindow.event)
I saw a post reporting the same error above, but did not see any resolution. Like the above poster, I would like to have the Explorer opening a new Window that looks and feels like (and is)the InternetExplorer where I can capture some events.
Anybody else seen this, how did they get around it?
Great article and discussion, even quite some time after original publishing this was the only helpful source of information that numerous google searches came up with.
Thanks,
- Stephan
# re: Handling mshtml Document Events without Mouse lockups
Particulary onclick event.
I tried to subscribe using the technique desbribe in this article to all onclick events possibles. Which means, all frames (recursivly) document onclick & body onclick events.
I'm getting the onclick event of every thing outside the iframe, but not in.
If I subscribe directly to the event as :
AddHandler BROWSER.Document.onclick, AddressOf METHOD (VB)
BROWSER.Document.onclick += METHOD (C#)
then i get the mouse events are blocked until a wander else where and come couple of times then it will start to work, but ALL working. Which means, that the Iframe events are captured.
Someone has an idea one this one ?
# re: Handling mshtml Document Events without Mouse lockups
The way to go is to have the DOM.External configured to an object of your own.
Then via javascript (which can be added on DocumentComplete) add :
function init(){
var IFrame = document.getElementById('R0');
IFrame.onreadystatechange = function() {
//Attach your events here to your external method. (if to external directly doesn't work, add a method which will call your external method).
};
}
//To detect full loading
function statechange() {if (document.readyState == "complete"){init();}}
document.onreadystatechange = statechange;
# re: Handling mshtml Document Events without Mouse lockups
I've been fighting with this a bit and I'm finding attachEvent to be fairly opaque.
Thanks in advance.
# re: Handling mshtml Document Events without Mouse lockups
document.onkeydown += new HTMLDocumentEvents2_onkeydownEventHandler(Browser_OnKeyDown);
this following line gives me error - Cannot assign to keyword b'coz it's a group method??
i am working for the OnKeyDown Event handler .
just help me out in this
Cheers Rick
# re: Handling mshtml Document Events without Mouse lockups
Plz help
regards
Abhishek
# re: Handling mshtml Document Events without Mouse lockups
I believe it has something to do with threading. I viewed properties of the Document object with the thread that created the browser and it was fine. I then created a new thread and had it try to read the document and I got the 'InvalidCastException' trying to do the same thing.
# re: Handling mshtml Document Events without Mouse lockups
I am sorry if I am being a n00b. But if I wanted to handle multiple events (onclick, onmouseover etc.), how would I go about doing that?
Is the following code legit?
DHTMLEventHandler Handler_OnClick = new DHTMLEventHandler(doc);
Handler_OnClick.Handler += new DHTMLEvent(my_Handler_OnClick);
DHTMLEventHandler Handler_OnMouseOver = new DHTMLEventHandler(doc);
Handler_OnMouseOver.Handler += new DHTMLEvent(my_Handler_OnMouseOver);
Is there a way that we can use the same event handler object for different type of events?
Aaron.
# re: Handling mshtml Document Events without Mouse lockups
This is in response to Stephan Lips. He is getting the Invalid Cast exception.
From some testing I did, Jack L. is correct. It is thread related. I found that the only thread I could reference the document.parentWindow property was from the Main thread (the first one created by the CLR). I am not sure about accessing other properties from other threads.
At first I tried attaching to the document from a thread I created. I used this thread as the only one I referenced the document properties. It was able to reference all properties EXCEPT the parentWindow. However even in this scenario, I was able to reference the parentWindow property from the main thread.
The trick is that the events caught by the handler described above are running on another thread it seems specifically created just to handle the event! If you reference the parentWindow property from this thread you get the Invalid Cast Exception. You have to get the code needed to handle the event running in the main thread. If it is windows form application, you can use the control.Invoke method. Otherwise you need to create some means of switching to the main thread to execute your event code.
I did this by creating a queue of items that has an instance of a delegate pointing to the event logic, any parameters, a return value, and an 'done' autoresetevent. The main thread sits in a loop waiting on an 'itemisqueued' autoresetevent. When an item is queued the 'itemisqueued' autoresetevent is set, and this thread waits for the 'done' autoresetevent to be set. The main thread then pulls the entry off the queue, invokes the routine pointed to by the delegate, saves any return value and then sets the 'done' event and waits for another item on the queue. Of course the main thread is only servicing this queue and not much else.
# re: Handling mshtml Document Events without Mouse lockups
The basic goal is to catch the active tab in IE7 so that a variable will be turned on for active tab and will be turned off for all other inactive tabs.
Please help me asap, it will be greatly appreciated.
Thanks in advance.
Mujtaba Panjwani
# re: Handling mshtml Document Events without Mouse lockups
Ive tried the 2.0 code for making the generic event object, but I cant get to caputure any events.
Thanks
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
Here's the code that'll seems to work within WPF:
private void webBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
mshtml.HTMLDocument doc = webBrowser.Document as HTMLDocument;
if (doc != null)
{
DHTMLEventHandler Handler = new DHTMLEventHandler(doc);
Handler.Handler += new DHTMLEvent(DOMEventHandler);
((DispHTMLDocument)doc).oncontextmenu = Handler;
}
}
private void DOMEventHandler(IHTMLEventObj pEvtObj)
{
pEvtObj.returnValue = false;
}
# re: Handling mshtml Document Events without Mouse lockups
How can I have something similar for IHTMLElement2 ondragstart, ondrag, ondrop? The handler should be connected to the HTMLElement not the HTMLDocument, right?
# re: Handling mshtml Document Events without Mouse lockups
i Been Trying To handle the values for onkeydown and onkeypress events but cannot retrive these values as there is on the keycode value which can be retrived using the above code the problem is that is always gives the valu 65 either the value is "A" or "a" how to differentiate that I'm trying to make a keyboard driver using rick's code.
can any had faced this issue
need help
Ameet
# re: Handling mshtml Document Events without Mouse lockups
This is a great blog. I'm hoping to resilve my issue ASAP.
I'm sorry to writen bad english.
Here is my C# code:
mshtml.IHTMLElement eHTML = null; mshtml.IHTMLDocument2 html_doc = null; html_doc = oIE.Document as mshtml.IHTMLDocument2; DispHTMLDocument html = (DispHTMLDocument)html_doc; eHTML = html.getElementById("textVal"); eHTML.innerText = "2"; mshtml.IHTMLElementCollection go = (mshtml.IHTMLElementCollection)Goihtml_doc.all; mshtml.HTMLFormElement goForm = (mshtml.HTMLFormElement)go.item("frmLinks_1", 0); goForm.submit();
I'm looking to put the dynamically Value internally into TextBox;
but its getting an error & not able to put the value into textBox.
Second Scenario that I need also:
How to execute Java Script function to clinking on
<a href='#' onClick='changePageID(3); return false;'>3</a>
link . Below is HTML code
<div class='pagBG pagLH'> <div class='flLeft font12 pagLH'> <img ='http://static.naukimg.com/rstatic/images/bck_disable.gif' alt='' width='16' height='16' hspace='2' vspace='8' border='0' /> <img src='http://static.naukimg.com/rstatic/images/bck1_disable.gif' alt='' width='16' height='16' hspace='2' vspace='8' border='0' /></div> <div class='flLeft font12 mainPadLR pagLH'><strong>1</strong> <a href='#' onClick='changePageID(2); return false;'>2</a> <a href='#' onClick='changePageID(3); return false;'>3</a> <a href='#' onClick='changePageID(4); return false;'>4</a> <a href='#' onClick='changePageID(5); return false;'>5</a> </div><div class='flLeft font12 pagLH'>...</div> <div class='flLeft font12 pagLH'> of <a href='#' onClick='changePageID(6); return false;'>6</a> </div><div class='flLeft font12 pagLH'> <a href='#' onClick='changePageID(2); return false;'> <img src='http://static.naukimg.com/rstatic/images/fwd1_enable.gif' alt='' width='16' height='16' hspace='2' vspace='8' border='0' /></a> <a href='#' onClick='changePageID(6); return false;'> <img src='http://static.naukimg.com/rstatic/images/fwd_enable.gif' alt='' width='16' height='16' hspace='2' vspace='8' border='0' /></a></div>
# re: Handling mshtml Document Events without Mouse lockups
Error 2 Ambiguity between 'mshtml.DispHTMLDocument.oncontextmenu' and 'mshtml.HTMLDocumentEvents_Event.oncontextmenu'
I am sing a BHO which unfortunately only allows a hook via ShDocVw
I tried to set it to System.Windows.Forms.WebBrowser but it then won't perform the onDocumentComplete method
So many people have written about this but I have not found a definitive answer
# re: Handling mshtml Document Events without Mouse lockups
# re: Handling mshtml Document Events without Mouse lockups
for those of you who are getting
"Error 2 Ambiguity between 'mshtml.DispHTMLDocument.oncontextmenu' and 'mshtml.HTMLDocumentEvents_Event.oncontextmenu'"
To correct this, change
doc.oncontextmenu = Handler;
DispHTMLDocument dispDoc = doc; dispDoc.oncontextmenu = Handler;
This is because the class HTMLDocument implements two interfaces, DispHTMLDocument and HTMLDocumentEvents_Event. Both interfaces have something named 'oncontextmenu' (or onmouseclick, or whatever) - one's an event, one's an object - so the compiler doesn't know which one you're trying to set. You want to set the one from DispHTMLDocument (the object).
As to why setting the object to a custom handler works, but setting the event doesn't, I have no idea.
# re: Handling mshtml Document Events without Mouse lockups
http://social.msdn.microsoft.com/forums/en-US/ieextensiondevelopment/thread/e69909f0-d883-462d-be1d-792f016ef77e/
# re: Handling mshtml Document Events without Mouse lockups
My Solution:
public void ExecuteJavascript(string javascript) { try { if (axWebBrowser1.InvokeRequired) axWebBrowser1.Invoke(new delSendJavascript(sendJavascript), new object[] { javascript }); else sendJavascript(javascript); } catch (Exception ex) { Console.WriteLine(ex.ToString()); // ACCESS DENIED?? Install IE7! } } private delegate void delSendJavascript(string javascript); private void sendJavascript(string javascript) { mshtml.IHTMLDocument2 d = ((mshtml.IHTMLDocument2)axWebBrowser1.Document); d.parentWindow.execScript(javascript, "JavaScript"); }
# re: Handling mshtml Document Events without Mouse lockups
I have one sample project to automate Internet explorer in VB 6.0. The same thing when I am trying to do with .Net its just hangs my Internet explorer document. I am not able to type or click on any control on the page.
Here is the sample code block.
Imports SHDocVw Imports mshtml Public Class FrmRecorder Dim WithEvents IE As New SHDocVw.InternetExplorer Dim WithEvents HtmDoc As HTMLDocument Private Sub FrmRecorder_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load IE.Visible = True IE.Navigate("www.google.com") Do While IE.Busy Application.DoEvents() Loop End Sub Private Function HtmDoc_onclick() As Boolean Handles HtmDoc.onclick MsgBox(HtmDoc.activeElement.tagName) End Function Private Sub IE_DocumentComplete(ByVal pDisp As Object, ByRef URL As Object) Handles IE.DocumentComplete HtmDoc = IE.Document End Sub End Class
Can anybody please help me out in this issue?
I am in big trouble.
Thanks in advance.
# re: Handling mshtml Document Events without Mouse lockups
Imports mshtml Imports SHDocVw Public Class frmRecorder Dim HtmDoc As mshtml.HTMLDocument Dim WithEvents Ie As New SHDocVw.InternetExplorer Private Sub Ie_DocumentComplete(ByVal pDisp As Object, ByRef URL As Object) Handles Ie.DocumentComplete HtmDoc = Ie.Document '' This is your declaration It doesn't resolved my issue 'AddHandler HtmDoc.onclick, AddressOf HtmDoc_onclick '' I tried with below code AddHandler CType(HtmDoc, _ mshtml.HTMLDocumentEvents2_Event).onclick, AddressOf HtmDoc_onclick End Sub 'Private Function HtmDoc_onclick() As Boolean ' MsgBox(HtmDoc.activeElement.tagName) 'End Function Private Function HtmDoc_onclick(ByVal e As mshtml.IHTMLEventObj) As Boolean MsgBox(HtmDoc.activeElement.tagName) MsgBox(e.srcElement.tagName.ToString()) End Function Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Ie.Navigate("www.google.com") Ie.Visible = True End Sub End Class
I need to get focusin and focusout events to check the changes user made in input controls at the time of recording.
# re: Handling mshtml Document Events without Mouse lockups
I am working on VB.Net and I have used mshtml events. When I use mshtml events on Internet Explorer at Document level, all the input elements are locked and cursor doesnot appear in the Internet Explorer which disables the user to enter the data in the input fields.
I debuged the issue and found that when the code enters into the event the Thread Apartment state changes to MTA which was in STA at the start of the program, which disables us to access the elements inside the HTML Document which are present under FRAMES.
Do you have any idea about such issue?
Thanks and Regards,
Ravikanth
# re: Handling mshtml Document Events without Mouse lockups
mshtml.DispHTMLDocument doc = this._browser.Document.DomDocument as mshtml.DispHTMLDocument; DHTMLEventHandler mouseMoveHandler = new DHTMLEventHandler(doc); mouseMoveHandler.Handler += new DHTMLEvent(onmousemove_handler); doc.onmousemove = mouseMoveHandler;
///
/// Generic HTML DOM Event method handler.
///
public delegate void DHTMLEvent(mshtml.IHTMLEventObj e);
///
/// Generic Event handler for HTML DOM objects.
/// Handles a basic event object which receives an IHTMLEventObj which
/// applies to all document events raised.
///
public class DHTMLEventHandler
{
public DHTMLEvent Handler;
mshtml.DispHTMLDocument Document;
public DHTMLEventHandler(mshtml.DispHTMLDocument doc)
{
this.Document = doc;
}
[DispId(0)]
public void Call()
{
Handler(Document.parentWindow.@event);
}
}
However, the onmousemove_handler is not called at all. I have tried other events as well, but none got triggered either.
# re: Handling mshtml Document Events without Mouse lockups
I'm facing this challenge but in VB 2008.
It looks like whatever event I add a handler for, all other events become ignored.
A HTML page loads and I hook the onmouseover event. The handler writes everything I mouseover to a list (as an example I found on Microsoft does) but the browser does not respond to anything else (mouse clicks, double clicks, or keystrokes) BUT it does respond to mousewheel actions and the backspace key...
I see that some found success in other implementations... Has anyone found success in VB 2008?
# re: Handling mshtml Document Events without Mouse lockups
I created a sample project (C#, VS 2010) with the exact same code and I don't see the events ever being fired..
# re: Handling mshtml Document Events without Mouse lockups
HTMLDocument doc = this.Document as HTMLDocument ;
DHTMLEventHandler Handler = new DHTMLEventHandler( doc );
Handler.Handler += new DHTMLEvent(this.Browser_ContextMenuStandardEvent);
doc.oncontextmenu = Handler;
This code displays in my program an ambiguity range error. So i've just modified the Navigated void method
My edit is given below :
HTMLDocument doc = this.Webpano.Document as HTMLDocument;
DispHTMLDocument docx = (DispHTMLDocument)doc; # Added line ----------------------------------------------------
DHTMLEventHandler Handler = new DHTMLEventHandler(doc);
Handler.Handler += new DHTMLEvent(this.Browser_ContextMenuStandardEvent);
docx.oncontextmenu = Handler; # Modified line -------------------------------
# re: Handling mshtml Document Events without Mouse lockups