在基于CDHtmlDialog类的对话框使用OnBeforeNavigate2已经有很多人给出了方法
http://alee201.blog.163.com/blog/static/277908512007313113733617/
http://bbs.csdn.net/topics/390411927?page=1
但是正如第二个链接中4楼的人提出的问题”该方法我早就试过,却是起作用,但是只要DECLARE_EVENTSINK_MAP(),那么BEGIN_DHTML_EVENT_MAP就不起作用,也就是说,html中的button,onButton事件就没用了,不知道怎么回事。“,我也碰到了类似的问题,就是一旦在OnBeforeNavigate2事件中Cancel了当前页面继续浏览,页面上的原来的元素操作就收不到消息继续工作了,经过1天的研究,找到了解决方法。
原理上就是在OnBeforeNavigate2事件中设置Cancel参数为TRUE,确实会取消页面的浏览,但是仍然会触发DocumentComplete事件,而在CDHtmlDialog类中DocumentComplete事件处理程序不管是否取消了页面浏览都会进行一定的工作,这些工作在取消浏览时会造成一定的错误,然后页面上的原来的元素操作就收不到消息继续工作了。
说了原理,下面给出具体的解决方法
实现OnBeforeNavigate2方法时,同时实现DocumentComplete方法
在.h文件中加入
protected: DECLARE_EVENTSINK_MAP() void OnBeforeNavigate2(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel); void OnDocumentCompleteThis(LPDISPATCH pDisp, VARIANT* URL); BOOL m_Cancel;
在.cpp文件中分别接入如下代码片段
BEGIN_EVENTSINK_MAP(CWebSizeWndTestDlg, CDHtmlDialog) ON_EVENT(CWebSizeWndTestDlg, AFX_IDC_BROWSER, 250 /* BeforeNavigate2 */, OnBeforeNavigate2, VTS_DISPATCH VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PVARIANT VTS_PBOOL) ON_EVENT(CWebSizeWndTestDlg, AFX_IDC_BROWSER, 259 /* DocumentComplete */, OnDocumentCompleteThis, VTS_DISPATCH VTS_PVARIANT) END_EVENTSINK_MAP()
void CWebSizeWndTestDlg::OnBeforeNavigate2(LPDISPATCH pDisp, VARIANT FAR* URL, VARIANT FAR* Flags, VARIANT FAR* TargetFrameName, VARIANT FAR* PostData, VARIANT FAR* Headers, BOOL FAR* Cancel) { //*Cancel = FALSE; //if (condition) // *Cancel = TRUE; if (*Cancel) m_Cancel = TRUE; else _OnBeforeNavigate2(pDisp, URL, Flags, TargetFrameName, PostData, Headers, Cancel); } void CWebSizeWndTestDlg::OnDocumentCompleteThis(LPDISPATCH pDisp, VARIANT* URL) { if (m_Cancel) m_Cancel = FALSE; else _OnDocumentComplete(pDisp, URL); }
并且别忘了在初始化时将m_Cancel设置为FALSE,不然第一个正常页面都加载不进来。
这样如果取消了OnBeforeNavigate2,就不让调用CDHtmlDialog的DocumentComplete的事件处理程序,这样就没有问题了。