When the page displayed in our CDHtmlDialog does an Asp.Net AJAX UpdatePanel we get a navigate event, but everything after that seems to be lost. We don't have a document anymore or get any mouse events on the page.
Looks like I made the original post as an unregistered user, so I don't think I can edit it. We were able to work around the original issue, but it came up again in a different context (really starting to hate CDHTMLDialog).
Here is the cause of the problem:
Javascript calls are causing a Navigate event, and CDHtmlDialog::OnBeforeNavigate gets called and disconnects and deletes the IHTMLDocument2. Unfortunately it's not a true Navigate since the page never changed. This means CDHtmlDialog::OnNavigateComplete is never called to get the document back.
To make matters worse, when I override CDHtmlDialog::OnBeforeNavigate I find the URL string is unreadable (bug)?
The simplest (best?) solution:
We need to intercept the Before Navigate event, and only call the CDHtmlDialog's _OnBeforeNavigate2 if the URL isn't a javascript action:
BEGIN_EVENTSINK_MAP(CMyHTMLDlg, CDHtmlDialog)
ON_EVENT(CMyHTMLDlg, AFX_IDC_BROWSER, DISPID_BEFORENAVIGATE2, OnBeforeNavigate2, VTS_DISPATCH VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_VARIANT VTS_PBOOL)
END_EVENTSINK_MAP()
void CMyHTMLDlg::OnBeforeNavigate2(LPDISPATCH pDisp, VARIANT* URL,VARIANT* Flags, VARIANT* TargetFrameName, VARIANT* PostData,VARIANT* Headers, BOOL* Cancel)
{
...
if (URL != NULL)
{
// Check if navigation is to a folder..
CString url = CString(*URL);
if(url.Left(11) != _T("javascript:"))
{
_OnBeforeNavigate2(pDisp, URL, Flags, TargetFrameName, PostData, Headers, (BOOL*)Cancel);
// If dynamic linking MFC then the above handler doesn't exist. Need to call OnBeforeNavigate direct.
// This is from a code site, and it compiles, but I've never tested it to see if it works.
//CDHtmlDialog::OnBeforeNavigate(pDisp,(LPCSTR)URL);
}
}
}
Most of this is pretty standard for setting up a CDHtmlDialog subclass, and it's pretty simple actually, but it took me a bit to figure out how to handle JavaScript. Unfortunately, I'm not sure how this will work if the JavaScript is making dynamic changes to the page itself.
A couple notes:
- If the navigation needs to be completely canceled here, then set *Cancel = TRUE and don't call _OnBeforeNavigate2. Be careful here because this also cancels any JavaScript actions.
- It wasn't clear until I saw the source, but CDHtmlDialog::_OnBeforeNavigate2 just calls CDHtmlDialog::OnBeforeNavigate.