In the documentation of the IDocHostUIHandler Interface, there is a paragraph about the default UI handler provided by IE when talking about a memory leak caused by using ICustomDoc from a BHO:
To avoid a memory leak:
1. Always forward the IDocHostUIHandler::ShowUI and
IDocHostUIHandler::HideUI methods to the original handler.
2. Release the pointer to the original UI handler when your object is called
with IObjectWithSite::SetSite(NULL).
How to get the host interface in order to release it?
While not officially supported, you can still get a reference to the original IDocHostUIHandler
in order to pass calls through on all of the methods you don't plan on overriding in your BHO.
First you cast the document as an IOleObject
and then call GetClientSite
in order to obtain the original IOleClientSite
object. This can then be cast to either IDocHostUIHandler
or IOleCommandTarget
in order to call the methods from those interfaces on the original handler/target.
Here is an example code snippet from the DocumentComplete event of a C# BHO (Explorer
is an instance of ShDocVw.WebBrowserClass
, UIHandler
is my own IDocHostUIHandler
class which passes calls through to the object passed in the initializer, and all of the interfaces were taken directly from http://pinvoke.net):
IOleObject obj = Explorer.Document as IOleObject;
if (obj != null)
{
IOleClientSite cs = null;
obj.GetClientSite(ref cs);
if (cs != null)
{
ICustomDoc cDoc = Explorer.Document as ICustomDoc;
if (cDoc != null)
{
cDoc.SetUIHandler(new UIHandler(cs));
}
}
}
This was adapted from C++ code available in the PopupBlocker project available here http://www.codeproject.com/Articles/4003/Popup-Window-Blocker