关于MFC项目中使用WebBrowser控件禁止脚本错误的方法

最近一个项目中要在对话框上使用WebBrowser控件进行页面浏览,但在开发过程中发现WebBrowser控件会在浏览一些页面的时候出现 JavaScript脚本错误,严重影响用户体验,而在IE和其他第三方浏览器中均没有这个现象。于是搜索一下发现原来可以通过下面的代码禁止这个错误提示:
  1. m_WebBrowser.put_Silent(TRUE);//禁止脚本错误提示  

效果非常好,可以说立竿见影。但是随之问题又来了,在登录银行网站时会出现无法打开网页的错误,原来这个Silent把银行的选择证书窗口也给禁止了。
翻了翻MSDN,发现原来这个参数要么都不禁止,要么都禁止……这显然不符合要求
搜索引擎真是个好东西,就在准备放弃的时候发现这么一篇文章CDHtmlDialog探索----WebBrowser扩展和网页Javascript错误处理
这会儿真想对着thinkingfor鞠一个大大的躬,真的。
因为一直都搞不懂COM这个东西,所以就抱着试试看的想法把thinkingfor的代码加进工程一编译,除了少数头文件等改动以外,完美运行。
为了备忘也希望能给遇到相同问题的人一点帮助,故将编译通过的代码列出,环境vs2008 + xp
代码如下

//CMyControlSite.h

    #pragma once      
    #include "afxocc.h"      
    #include "Mshtml.h"//应该加入这个头文件      
    #include "Mshtmhst.h"//这个也是      
    class CMyControlSite :public COleControlSite     
    {     
    public:     
        CMyControlSite(COleControlContainer *pCntr):COleControlSite(pCntr) {}     
        ~CMyControlSite(void);     
    protected:     
        DECLARE_INTERFACE_MAP()       
        BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget)       
            STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText);       
            STDMETHOD(Exec)(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut);       
        END_INTERFACE_PART(OleCommandTarget)       
    };    



(OLECMDID 信息参看下篇博文)

  1. //  CMyControlSite.cpp<pre name="code" class="cpp">    #include "StdAfx.h"       
        #include "MyControlSite.h"   
              
        BEGIN_INTERFACE_MAP(CMyControlSite, COleControlSite)       
            INTERFACE_PART(CMyControlSite, IID_IOleCommandTarget, OleCommandTarget)     
        END_INTERFACE_MAP()       
             
             
             
        CMyControlSite::~CMyControlSite(void)     
        {     
        }     
             
        HRESULT CMyControlSite::XOleCommandTarget::Exec       
        (const GUID* pguidCmdGroup, DWORD nCmdID,       
         DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut )       
        {       
            HRESULT hr = OLECMDERR_E_NOTSUPPORTED;       
            //return S_OK;        
            if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler))       
            {       
             
                switch (nCmdID)        
                {       
             
                case OLECMDID_SHOWSCRIPTERROR:       
                    {       
                        IHTMLDocument2*             pDoc = NULL;       
                        IHTMLWindow2*               pWindow = NULL;       
                        IHTMLEventObj*              pEventObj = NULL;       
                        BSTR                        rgwszNames[5] =        
                        {        
                            SysAllocString(L"errLine"),       
                            SysAllocString(L"errCharacter"),       
                            SysAllocString(L"errCode"),       
                            SysAllocString(L"errMsg"),       
                            SysAllocString(L"errUrl")       
                        };       
                        DISPID                      rgDispIDs[5];       
                        VARIANT                     rgvaEventInfo[5];       
                        DISPPARAMS                  params;       
                        BOOL                        fContinueRunningScripts = false;  //修改此处为false禁止脚本错误提示      
             
                        params.cArgs = 0;       
                        params.cNamedArgs = 0;       
                             
                        hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc);           
                              
                        hr = pDoc->get_parentWindow(&pWindow);       
                        pDoc->Release();       
                             
                        hr = pWindow->get_event(&pEventObj);       
                             
                        for (int i = 0; i < 5; i++)        
                        {         
                                 
                            hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1,        
                                LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]);       
                             
                            hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL,       
                                LOCALE_SYSTEM_DEFAULT,       
                                DISPATCH_PROPERTYGET, ¶ms, &rgvaEventInfo[i],       
                                NULL, NULL);       
                            //可以在此记录错误信息                    //必须使用SysFreeString来释放SysAllocString分配的内存,SysAllocString在分配的内存中记录了字符的长度      
                            SysFreeString(rgwszNames[i]);       
                        }       
             
                        // At this point, you would normally alert the user with         
                        // the information about the error, which is now contained        
                        // in rgvaEventInfo[]. Or, you could just exit silently.        
             
                        (*pvaOut).vt = VT_BOOL;       
                        if (fContinueRunningScripts)       
                        {       
                            // 在页面中继续执行脚本       
                            (*pvaOut).boolVal = VARIANT_TRUE;       
                        }       
                        else      
                        {       
                            // 停止在页面中执行脚本        
                            (*pvaOut).boolVal = VARIANT_FALSE;          
                        }        
                        break;       
                    }       
                default:       
                    hr =OLECMDERR_E_NOTSUPPORTED;      
                    break;       
                }       
            }       
            else      
            {       
                hr = OLECMDERR_E_UNKNOWNGROUP;     
            }       
            return (hr);       
        }       
             
             
        ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::AddRef()        
        {        
            METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)        
                return pThis->ExternalAddRef();        
        }        
             
             
        ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::Release()        
        {        
            METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)        
                return pThis->ExternalRelease();        
        }        
             
        HRESULT FAR EXPORT CMyControlSite::XOleCommandTarget::QueryInterface(REFIID riid, void **ppvObj)        
        {        
            METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)        
                HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);        
            return hr;        
        }       
             
        STDMETHODIMP CMyControlSite::XOleCommandTarget::QueryStatus(        
             const GUID __RPC_FAR *pguidCmdGroup,        
             ULONG cCmds,        
             OLECMD __RPC_FAR prgCmds[ ],        
             OLECMDTEXT __RPC_FAR *pCmdText        
            )        
        {        
            METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)        
                return OLECMDERR_E_NOTSUPPORTED;        
        }    

     
     

对话框头文件加入声明:

 
    virtual BOOL CreateControlSite(COleControlContainer* pContainer, COleControlSite** ppSite, UINT  nID , REFCLSID  clsid );  

对应源文件:


    BOOL CXDlg::CreateControlSite(COleControlContainer* pContainer,      
            COleControlSite** ppSite, UINT  nID , REFCLSID  clsid )     
    {     
            if(ppSite == NULL)     
        {     
            ASSERT(FALSE);     
            return FALSE;     
        }     
         
        CMyControlSite *pBrowserSite =      
            new CMyControlSite (pContainer);//      
        if (!pBrowserSite)     
            return FALSE;     
         
        *ppSite = pBrowserSite;     
        return TRUE;     
    }    



此外,thinkingfor原文中为CDHtmlDialog,同样适用于CDialog。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值