页面脚本在运行时,如果出现错误,默认情况下会弹出一个对话框,告诉你脚本不正确,要不要继续运行什么的。CHTMLView中没有处理这种情况的默认方法。如果要响应这类事件,需要做2件事,1 创建一个新的类,继承自COleControl或它的派生类,并实现IOleCommandTarget接口。2 替换CHTMLView类中的CreateControlSite函数,以返回刚才创建那个类的实例。
脚本引擎在遇到未处理的错误时,它会查询容器,看该容器是不是已经实现了 IOleCommandTarget 接口。如果是,web 浏览器控件将以参数OLECMDID_SHOWSCRIPTERROR调用IOleCommandTarget::Exec 方法。如果函数返回 S_OK,那么浏览器对象就不会弹出错误对话框了。
CHTMLView 本身并不是这样的容器,所以它无法直接获得这些事件。但CHTMLView有一个函数CreateControlSite,它用来创建所需要的对象容器。如果我们替换这个函数,并返回自己的容器对象,就可以接收这类事件了。
这样的对象容器可以继承自COleControlSite,并实现IOlecommandTaget接口。当脚本出错,它会调用IOleCommandTarget中的Exec来处理这个事件。Exec的申明是这样的
STDMETHODIMP CSiteView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt,VARIANT *pvaIn,VARIANT *pvaOut)
其中nCmdID指明是哪种事件。如果其值为OLECMDID_SHOWSCRIPTERROR ,说明发生脚本运行错误,此时令函数返回S_OK,那么就不会弹出对话框了。
简单的代码如下
头文件
.cpp文件
IOleCommandTarget基本上就处理完了。再来看看CHTMLView. CHTMLView 的创建过程是这样的 CHTMLView::Create---->CWnd::CreateControl-->COleControlContainer::CreateControl-->CHTMLView::CreateControlSite.而CreateControlSite的定义也比较简单
我们在自己的类中重写CreateControlSite并返回刚刚完成的那个类的实例就可以了。
简单的代码如下
到这里,大体的样子就基本完成了。CHTMLView的默认ControlSite是CHTMLControlSite,它被定义在viewhtml.cpp文件中,所以我们没有办法继承它。如果要实现它原有的一些功能,比如ShowContenxtMenu之类的,可以参考CHTMLControlSite的代码来写,没有多少。
参考文档
微软知识库文章 Q261003 How to handle script errors as a WebBrowser control host (http://support.microsoft.com/kb/261003)
优快云文档 WebBrowser中Script错误调试的对话框 http://topic.youkuaiyun.com/t/20061105/02/5133903.html
大牛 蒋晟 的文章 Hook DHMTL Commands http://www.joycode.com/jiangsheng/archive/2005/07/09/58754.joy