用CHTMLView 来处理script脚本错误

页面脚本在运行时,如果出现错误,默认情况下会弹出一个对话框,告诉你脚本不正确,要不要继续运行什么的。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,那么就不会弹出对话框了。

 

简单的代码如下

头文件

  1. //CSiteControlSite.h  
  2.   
  3. #include <afxocc.h>  
  4.   
  5. //CSiteView 继承自CHTMLView  
  6. class CSiteView;  
  7.   
  8. class CSiteControlSite : public COleControlSite  
  9. {  
  10. public:  
  11.   
  12.     CSiteControlSite(COleControlContainer* pCtrlCont)   
  13.         : COleControlSite(pCtrlCont)  
  14.     {  
  15.     };  
  16.   
  17.     ~CSiteControlSite()  
  18.     {  
  19.     }  
  20.   
  21.     CSiteView * GetView() const;  
  22.   
  23. protected:  
  24. //关键的代码在这里  
  25.     DECLARE_INTERFACE_MAP()  
  26.   
  27.     BEGIN_INTERFACE_PART(CmdTargetObj, IOleCommandTarget)  
  28.          STDMETHOD(QueryStatus)(const GUID*, ULONG, OLECMD[], OLECMDTEXT*);  
  29.          STDMETHOD(Exec)(const GUID*, DWORDDWORD, VARIANTARG*,VARIANTARG*);  
  30.       END_INTERFACE_PART(CmdTargetObj)  
  31.   
  32.   
  33.     friend class CSiteView;  
  34. };  

.cpp文件

  1. BEGIN_INTERFACE_MAP(CSiteControlSite, COleControlSite)  
  2.       INTERFACE_PART(CSiteControlSite, IID_IOleCommandTarget, CmdTargetObj)  
  3. END_INTERFACE_MAP()  
  4.   
  5.   
  6. CSiteView * CSiteControlSite::GetView() const  
  7. {  
  8.     return STATIC_DOWNCAST(CSiteView, m_pCtrlCont->m_pWnd);  
  9. }  
  10.   
  11. ULONG FAR EXPORT CSiteControlSite::XCmdTargetObj::AddRef()  
  12. {  
  13.     METHOD_PROLOGUE(CSiteControlSite, CmdTargetObj)  
  14.     return pThis->ExternalAddRef();  
  15. }  
  16.   
  17. ULONG FAR EXPORT CSiteControlSite::XCmdTargetObj::Release()  
  18. {  
  19.     METHOD_PROLOGUE(CSiteControlSite, CmdTargetObj)  
  20.     return pThis->ExternalRelease();  
  21. }  
  22.   
  23. HRESULT FAR EXPORT CSiteControlSite::XCmdTargetObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)  
  24. {  
  25.     METHOD_PROLOGUE(CSiteControlSite, CmdTargetObj)  
  26.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);  
  27. }  
  28.   
  29. STDMETHODIMP CSiteControlSite::XCmdTargetObj::QueryStatus(const GUID* pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[],OLECMDTEXT* pcmdtext)  
  30. {  
  31.     METHOD_PROLOGUE(CSiteControlSite, CmdTargetObj)  
  32.           
  33.     return S_OK;  
  34. }  
  35.   
  36. STDMETHODIMP CSiteControlSite::XCmdTargetObj::Exec(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)  
  37. {  
  38.     METHOD_PROLOGUE(CSiteControlSite, CmdTargetObj)  
  39.          HRESULT hr = S_OK;  
  40.   
  41.     if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler))  
  42.     {  
  43.         switch (nCmdID)   
  44.         {  
  45.         case OLECMDID_SHOWSCRIPTERROR:  
  46.             {  
  47.                 // pvaOut 设置为TRUE,继续运行此scripts  
  48.                 (*pvaOut).vt = VT_BOOL;  
  49.                 (*pvaOut).boolVal = VARIANT_TRUE;  
  50.                 return S_OK;  
  51.                 break;  
  52.             }  
  53.         default:  
  54.             hr = OLECMDERR_E_NOTSUPPORTED;  
  55.             break;  
  56.         }  
  57.     }  
  58.     else  
  59.     {  
  60.         hr = OLECMDERR_E_UNKNOWNGROUP;  
  61.     }  
  62.     return (hr);  
  63. }  

 

  IOleCommandTarget基本上就处理完了。再来看看CHTMLView. CHTMLView 的创建过程是这样的 CHTMLView::Create---->CWnd::CreateControl-->COleControlContainer::CreateControl-->CHTMLView::CreateControlSite.而CreateControlSite的定义也比较简单

  1. BOOL CHtmlView::CreateControlSite(COleControlContainer* pContainer,   
  2.    COleControlSite** ppSite, UINT /* nID */, REFCLSID /* clsid */)  
  3. {  
  4.     ASSERT(ppSite != NULL);  
  5.     *ppSite = new CHtmlControlSite(pContainer);  
  6.     return TRUE;  
  7. }  
        

我们在自己的类中重写CreateControlSite并返回刚刚完成的那个类的实例就可以了。

简单的代码如下

  1. BOOL CSiteView::CreateControlSite(COleControlContainer* pContainer,   
  2.    COleControlSite** ppSite, UINT /* nID */, REFCLSID /* clsid */)  
  3. {  
  4.     ASSERT(ppSite != NULL);  
  5.     *ppSite = new CSiteControlSite(pContainer);  
  6.     return TRUE;  
  7. }  

 

到这里,大体的样子就基本完成了。CHTMLView的默认ControlSite是CHTMLControlSite,它被定义在viewhtml.cpp文件中,所以我们没有办法继承它。如果要实现它原有的一些功能,比如ShowContenxtMenu之类的,可以参考CHTMLControlSite的代码来写,没有多少。

 

 

参考文档

微软知识库文章 Q261003 How to handle script errors as a WebBrowser control host (http://support.microsoft.com/kb/261003)

CSDN文档 WebBrowser中Script错误调试的对话框  http://topic.csdn.net/t/20061105/02/5133903.html

大牛 蒋晟 的文章 Hook DHMTL Commands  http://www.joycode.com/jiangsheng/archive/2005/07/09/58754.joy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值