You need a custom implementation of IOleCommandTarget. If the
webbrowser encounters an unhandled script error, it will notify its
host, which in turn will notify the IOleCommandTarget for its
container. In order to catch and handle these messages, your Exec()
function needs to look something like this:
STDMETHODIMP CYourCommandTgtImpl::Exec(const GUID *pguidCmdGroup,
DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
HRESULT hr = pguidCmdGroup ? OLECMDERR_E_UNKNOWNGROUP :
OLECMDERR_E_NOTSUPPORTED;
if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup,
CGID_DocHostCommandHandler)) {
// Disable script error
if (nCmdID == OLECMDID_SHOWSCRIPTERROR) {
// handle your error here
hr = S_OK;
}
}
return hr;
}
You can get to the error object by calling QueryInterface() on pvaIn-
>punkVal to get an IHTMLDocument2 interface and then getting the
parent window, then the event from the window.
Yea, I have found other references on the web that say the same thing
you are saying. The problem I am running into is:
If I go off an create a brand new class that implements
IOleCommandTarget, it just sits there. Somewhere, somehow the
WebBrowser Control needs to get access to an instance of this class I
created that implements IOleCommandTarget so that WebBrowser Control
can call the Exec method on the Exec IOleCommandTarget interface.
I cannot find ANY documentation on how to let the WebBrowser Control
get access to the IOleCommandTarget.
I must admit, I wrote this code that hosts the WebBrowser Control two
and a half years ago and so I am rusty on lots of the finer details of
CAxWindows and how it connects to the host. I do see that on the
DWebBrowserEvents2::NavigateComplete2 I am wiring in a new
IDocHostUIHandler each time to do things like suppress the right click
menu and some other things. Do I need to wire in the implementation
of IOleCommandTarget at the same time? If so, how?
So the real question is: How does one wire in an implementation of
IOleCommandTarget into a ATL program that is hosting the WebBrowser
control.
Sam
Implement both IOleCommandTarget and IOleClientSite on the same
object. Then, you just have to hook the client site to the webbrowser
control itself. Here's a code snippet, from OnInitDialog() in my
CAxDialogImpl-based class:
RECT rc;
GetWindowRect(&rc);
// attach the IOleClientSite and IOleCommandTarget implementation
(pClientSite)
// to the IWebBrowser2 of the webbrowser control (pBrowser)
CComQIPtr<IOleObject> spOleObj(pBrowser);
CComQIPtr<IOleClientSite> spClientSite(pClientSite->GetUnknown());
spOleObj->SetClientSite(spClientSite);
// activate the OLE object (m_hWnd of the dialog)
spOleObj->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0,
m_hWnd, &rc);
Hope that helps!