Monday, July 21, 2008

Working With Microsoft.mshtml.dll and SHDocVw.dll

I was working On BHO for IE in C#. Initially i was not knowing any thing about BHO and IE extentions. I read articles and Architecture and related information from MSDN. Also I read Architecture of IE on MSDN.

But I got the best understanding of BHO onCode Project By Pavel Zolnikov. I have listed some problem that i had faced and Solution of those problem.

I was working On BHO TOOL BAR. I was trying to access Object element (<object> Tag), Image Element(<img> Tag), Embed Element (<embed> Tag). I had initially problem that how to get this element.

I had two solutions:

1) Use JavaScript to get the Element.

2) Retrieve the Object Directly from Page [as like. IE Developer ToolBar ]

I was using Both of them, because in many case 2nd approach is failed to detect the Object।


1.) Injection Javascript in any Web pages.

We can inject our own Javascript in any web page in IE.

//Explorer is Object of SHDocVw.WebBrowserClass

HTMLDocument htmlDoc = (HTMLDocument)this.Explorer.IWebBrowser_Document;

//inject Script
htmlDoc।parentWindow.execScript("alert('hello world !!')", "javascript");


2.) Handling Web Document Events.

You can directly handle events of Documents from your BHO as follows:

((mshtml.HTMLDocumentEvents2_Event)htmlDoc).onmousedown += newHTMLDocumentEvents2_onmousedownEventHandler(MyToolBar_onmousedown);


//Function is as follows:

//This will be raised when mousedown event is fired....when user try to click..(downs the mouse button)

void MyToolBar_onmousedown(IHTMLEventObj pEvtObj)
{
MessageBox.Show(pEvtObj.srcElement.tagName);
}

Now there was a Problem with this method...After Implementing above way of code...it was stop the actual events of the browser. Means No events on web Browser was fired. In Other words Events of Web Browser was Locked.

So it was a little and annoying problem, but I found solution for this problem Here By Rick Strahl


namespace MyToolBar
{
public delegate void DOMEvent(mshtml.IHTMLEventObj e);
public classDOMEventHandler
{

public DOMEvent Handler;
DispHTMLDocument Document;
public DOMEventHandler(DispHTMLDocument doc)
{
this.Document = doc;
}
[DispId(0)]
public voidCall()
{
Handler(Document.parentWindow.@event);
}
}
}


Above Class Can be used as :

//Explorer is Object of SHDocVw.WebBrowserClass

HTMLDocument htmlDoc = (HTMLDocument)this.Explorer.IWebBrowser_Document;

DispHTMLDocument doc = (DispHTMLDocument ) htmlDoc

DOMEventHandler onmousedownhandler = newDOMEventHandler (doc); onmousedownhandler.Handler += new DOMEvent(Mouse_Down); doc.onmousedown = onmousedownhandler;


//mouse Down Can be like this

public void Mouse_Down(mshtml.IHTMLEventObje)
{

MessageBox.Show(e.srcElement.tagName);

}

3.) Collecting All the Images From Web Page.

I was trying to access All the images from the Web Page.

It can be done one of the following way.

i.) By Document.Images Collection

//Explorer is Object of SHDocVw.WebBrowserClass

HTMLDocument htmlDoc = (HTMLDocument)this.Explorer.IWebBrowser_Document;
//get all the images of document
IHTMLElementCollection imgs = htmlDoc.images;
foreach (HTMLImgClass imgTag in imgs)
{
MessageBox.Show(imgTag.src);
}
ii.) By getElementsByTagName

HTMLDocument htmlDoc = (HTMLDocument)this.Explorer.IWebBrowser_Document;
//get all the images of document

IHTMLElementCollection imgs = htmlDoc.getElementsByTagName("img");
foreach (HTMLImgClass imgTag in imgs)
{
MessageBox.Show(imgTag.src);
}

4.) Accessing Content From Frames and IFrames.

The Biggest problem was to access content from frames and Iframes. I had tried lot to access content from Frame and Iframe. But it was giving me always IFrameElement or Access Denied Exception.


IHTMLElementCollection frames =
(IHTMLElementCollection) htmlDoc।getElementsByTagName("frame");

if (frames != null)
{

foreach (IHTMLElement frminframes)
{
(HTMLFrameElement)frm).contentWindow.execScript('alert('Hello From Frame')',"javascript");
}
}

Using Above CodeI was able to access the frame but it was giving Access Denied Exception.

I was also trying to attach event with Frame/Iframe Document but there was same problem.

Finally I got the solution from HERE.

I done as follows:


IHTMLElementCollection elcol = htmlDoc.getElementsByTagName("iframe");
foreach (IHTMLElement iel inelcol)

{

HTMLFrameElement frm = (HTMLFrameElement )iel;
DispHTMLDocument doc = (DispHTMLDocument)((SHDocVw.IWebBrowser2)frm).Document;
DOMEventHandler onmousedownhandler = new DOMEventHandler (doc);
onmousedownhandler।Handler += new DOMEvent(Mouse_Down); doc.onmousedown = onmousedownhandler;

}


5.) Get all the attributes of the Tag / Element.
I was required to get all the attributes of the tag. Attributes like height , width, src etc. I was able to get all the attribute as follows.
IHTMLElement element;
IHTMLDOMNode nd = (IHTMLDOMNode)element;

IHTMLAttributeCollection attribs = (IHTMLAttributeCollection )nd.attributes;
try
{
foreach (IHTMLDOMAttribute2 att in attribs)
{
if (((IHTMLDOMAttribute)att).specified)
{
MessageBox.Show(att.value);
}
}
}catch{}


No comments: