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

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

 

  1. m_WebBrowser.put_Silent(TRUE);//禁止脚本错误提示  
m_WebBrowser.put_Silent(TRUE);//禁止脚本错误提示


效果非常好,可以说立竿见影。但是随之问题又来了,在登录银行网站时会出现无法打开网页的错误,原来这个Silent把银行的选择证书窗口也给禁止了.

翻了翻MSDN,发现原来这个参数要么都不禁止,要么都禁止……这显然不符合要求

搜索引擎真是个好东西,就在准备放弃的时候发现这么一篇文章  CDHtmlDialog探索----WebBrowser扩展和网页Javascript错误处理 作者:thinkingfor

这会儿真想对着thinkingfor鞠一个大大的躬,真的。

因为一直都搞不懂COM这个东西,所以就抱着试试看的想法把thinkingfor的代码加进工程一编译,除了少数头文件等改动以外,完美运行。

为了备忘也希望能给遇到相同问题的人一点帮助,故将编译通过的代码列出,环境vs2008 + xp

代码如下:

01.CMyControlSite.h 

 
CMyControlSite.h[cpp] view plaincopyprint?
01.#pragma once   
02.#include "afxocc.h"   
03.#include "Mshtml.h"//应该加入这个头文件   
04.#include "Mshtmhst.h"//这个也是   
05.class CMyControlSite :public COleControlSite  
06.{  
07.public:  
08.    CMyControlSite(COleControlContainer *pCntr):COleControlSite(pCntr) {}  
09.    ~CMyControlSite(void);  
10.protected:  
11.    DECLARE_INTERFACE_MAP()    
12.    BEGIN_INTERFACE_PART(OleCommandTarget, IOleCommandTarget)    
13.        STDMETHOD(QueryStatus)(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText);    
14.        STDMETHOD(Exec)(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut);    
15.    END_INTERFACE_PART(OleCommandTarget)    
16.};  
01.CMyControlSite.cpp  



CMyControlSite.cpp[cpp] view plaincopyprint?
01.#include "StdAfx.h"   
02.#include "MyControlSite.h"   
03.  
04.  
05.BEGIN_INTERFACE_MAP(CMyControlSite, COleControlSite)    
06.    INTERFACE_PART(CMyControlSite, IID_IOleCommandTarget, OleCommandTarget)  
07.END_INTERFACE_MAP()    
08.  
09.  
10.  
11.CMyControlSite::~CMyControlSite(void)  
12.{  
13.}  
14.  
15.HRESULT CMyControlSite::XOleCommandTarget::Exec    
16.(const GUID* pguidCmdGroup, DWORD nCmdID,    
17. DWORD nCmdexecopt, VARIANTARG* pvaIn, VARIANTARG* pvaOut )    
18.{    
19.    HRESULT hr = OLECMDERR_E_NOTSUPPORTED;    
20.    //return S_OK;     
21.    if (pguidCmdGroup && IsEqualGUID(*pguidCmdGroup, CGID_DocHostCommandHandler))    
22.    {    
23.  
24.        switch (nCmdID)     
25.        {    
26.  
27.        case OLECMDID_SHOWSCRIPTERROR:    
28.            {    
29.                IHTMLDocument2*             pDoc = NULL;    
30.                IHTMLWindow2*               pWindow = NULL;    
31.                IHTMLEventObj*              pEventObj = NULL;    
32.                BSTR                        rgwszNames[5] =     
33.                {     
34.                    SysAllocString(L"errLine"),    
35.                    SysAllocString(L"errCharacter"),    
36.                    SysAllocString(L"errCode"),    
37.                    SysAllocString(L"errMsg"),    
38.                    SysAllocString(L"errUrl")    
39.                };    
40.                DISPID                      rgDispIDs[5];    
41.                VARIANT                     rgvaEventInfo[5];    
42.                DISPPARAMS                  params;    
43.                BOOL                        fContinueRunningScripts = false;  //修改此处为false禁止脚本错误提示   
44.  
45.                params.cArgs = 0;    
46.                params.cNamedArgs = 0;    
47.                  
48.                hr = pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2, (void **) &pDoc);        
49.                   
50.                hr = pDoc->get_parentWindow(&pWindow);    
51.                pDoc->Release();    
52.                  
53.                hr = pWindow->get_event(&pEventObj);    
54.                  
55.                for (int i = 0; i < 5; i++)     
56.                {      
57.                      
58.                    hr = pEventObj->GetIDsOfNames(IID_NULL, &rgwszNames[i], 1,     
59.                        LOCALE_SYSTEM_DEFAULT, &rgDispIDs[i]);    
60.                  
61.                    hr = pEventObj->Invoke(rgDispIDs[i], IID_NULL,    
62.                        LOCALE_SYSTEM_DEFAULT,    
63.                        DISPATCH_PROPERTYGET, ¶ms, &rgvaEventInfo[i],    
64.                        NULL, NULL);    
65.                    //可以在此记录错误信息                    //必须使用SysFreeString来释放SysAllocString分配的内存,SysAllocString在分配的内存中记录了字符的长度   
66.                    SysFreeString(rgwszNames[i]);    
67.                }    
68.  
69.                // At this point, you would normally alert the user with      
70.                // the information about the error, which is now contained     
71.                // in rgvaEventInfo[]. Or, you could just exit silently.     
72.  
73.                (*pvaOut).vt = VT_BOOL;    
74.                if (fContinueRunningScripts)    
75.                {    
76.                    // 在页面中继续执行脚本    
77.                    (*pvaOut).boolVal = VARIANT_TRUE;    
78.                }    
79.                else   
80.                {    
81.                    // 停止在页面中执行脚本     
82.                    (*pvaOut).boolVal = VARIANT_FALSE;       
83.                }     
84.                break;    
85.            }    
86.        default:    
87.            hr =OLECMDERR_E_NOTSUPPORTED;   
88.            break;    
89.        }    
90.    }    
91.    else   
92.    {    
93.        hr = OLECMDERR_E_UNKNOWNGROUP;  
94.    }    
95.    return (hr);    
96.}    
97.  
98.  
99.ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::AddRef()     
100.{     
101.    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)     
102.        return pThis->ExternalAddRef();     
103.}     
104.  
105.  
106.ULONG FAR EXPORT CMyControlSite::XOleCommandTarget::Release()     
107.{     
108.    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)     
109.        return pThis->ExternalRelease();     
110.}     
111.  
112.HRESULT FAR EXPORT CMyControlSite::XOleCommandTarget::QueryInterface(REFIID riid, void **ppvObj)     
113.{     
114.    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)     
115.        HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);     
116.    return hr;     
117.}    
118.  
119.STDMETHODIMP CMyControlSite::XOleCommandTarget::QueryStatus(     
120.    /* [unique][in] */ const GUID __RPC_FAR *pguidCmdGroup,     
121.    /* [in] */ ULONG cCmds,     
122.    /* [out][in][size_is] */ OLECMD __RPC_FAR prgCmds[ ],     
123.    /* [unique][out][in] */ OLECMDTEXT __RPC_FAR *pCmdText     
124.    )     
125.{     
126.    METHOD_PROLOGUE(CMyControlSite, OleCommandTarget)     
127.        return OLECMDERR_E_NOTSUPPORTED;     
128.}     

对话框头文件加入声明

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

对应源文件

01.BOOL CXDlg::CreateControlSite(COleControlContainer* pContainer,   
02.        COleControlSite** ppSite, UINT  nID , REFCLSID  clsid )  
03.{  
04.        if(ppSite == NULL)  
05.    {  
06.        ASSERT(FALSE);  
07.        return FALSE;  
08.    }  
09.  
10.    CMyControlSite *pBrowserSite =   
11.        new CMyControlSite (pContainer);//   
12.    if (!pBrowserSite)  
13.        return FALSE;  
14.  
15.    *ppSite = pBrowserSite;  
16.    return TRUE;  
17.}  


CDhtmlDialog同样也适用于CDialog

posted @ 2015-10-16 15:53  时光回眸  阅读(1179)  评论(0编辑  收藏  举报