So unfortunately I'm stuck writing a BHO for Internet Explorer. Its function is to inject an iframe into every web page the user visits, displaying some (relatively) constant information as the user goes about his or her business. I've managed the injection through a rather hacky series of mshtml casts, as follows, where Explorer is a WebBrowserClass object and foo.html is provided with the BHO's source:
IHTMLDocument2 document = (IHTMLDocument2) Explorer.Document;
IHTMLDocument3 doc3 = (IHTMLDocument3)document;
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "foo.html");
iframe.setAttribute("id", "iFrame");
iframe.setAttribute("style", "position: fixed; left: 0px; top: 0px; border: 0px; width: 100%; height: 45px; background-color: white");
IHTMLElementCollection iec = doc3.getElementsByTagName("body");
IHTMLElement elem = (IHTMLElement)iec.item(0);
IHTMLDOMNode domnode = (IHTMLDOMNode)elem;
domnode.appendChild((IHTMLDOMNode)iframe);
This works! I think. Sort of. It causes an infinite loop if I stick it in OnDocumentComplete, and it doesn't display any iframe either way. The issue with the loop is using Explorer's event listeners like OnDocumentComplete, as they get called whenever the page inside the iFrame finishes loading, which then calls the injection function, which then calls OnDocumentComplete, which... well, you get the idea. I've tried using OnNavigateComplete, but it still ends up loading multiple times on pages that are loading from multiple sources (like, for example, google's main search page with autocomplete enabled.) But even when it doesn't go into an infinite loop, I still don't end up with a visible iframe.
So I suppose this is two questions: 1) How do I actually get my iframe to appear? The injection code works (I've tried it with a simple javascript alert)... 2) How do I get my iframe to appear every time the user navigates to a new page or refreshes the current one without causing the BHO to go into an infinite loop?
Other potentially relevant functions:
void OnNavigateComplete(object pDisp, ref object URL)
{
if ((_currentDocument != null) && (isValidURL(_currentDocument.url)))
{
injectFrame();
}
}
void OnDocumentComplete(object pDisp, ref object URL)
{
if (Explorer.ReadyState == SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
{
_currentDocument = Explorer.Document as mshtml.HTMLDocument;
if (_currentDocument != null)
{
//injectFrame();
}
}
}
Okay, I think I've mostly figured this out. OnDocumentComplete's still getting called more than once, but I've sussed out all the issues with the frame... so while the iframe is loading multiple times, it's getting loaded in the same place.
The fix for the infinite loop was to hardcode the location of the toolbar, and check that url in OnDocumentComplete:
void OnDocumentComplete(object pDisp, ref object URL)
{
// _currentDocument = Explorer.Document as mshtml.HTMLDocumentClass;
if (Explorer.ReadyState == SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
{
_currentDocument = Explorer.Document as mshtml.HTMLDocument;
if (_currentDocument != null)
{
// we have a document - attach our events
// on onload event should go here if the document is now complete...
if (!URL.Equals("http://url.to/foo.html")) injectFrame();
}
else
{
// document is null?
// Debugger.ShowMessage("Tried to attach to document, but was null");
}
}
}
As far as the iframe goes, the Style attribute is apparently its own set of strings instead of just a regular string like every OTHER attribute. So instead of doing something like...
setAttribute("style","position: fixed; left: 0px; top: 0px; border: 0px; width: 100%; height: 45px; background-color: white");
I ended up having to do
iframe.style.setAttribute("position", "fixed");
iframe.style.left="0px";
iframe.style.top="0px";
iframe.style.border="0px";
iframe.style.width = "100%";
iframe.style.height="45px";
iframe.style.backgroundColor="white";
This whole thing has been a gigantic headache and I hope to never have to deal with it again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With