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

来源:互联网 发布:修车软件哪个好 编辑:程序博客网 时间:2024/05/01 00:48
最近一个项目中要在对话框上使用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 信息参看下篇博文)

    //  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。

0 0