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

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

 

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


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

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

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

这会儿真想对着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)  
};
CMyControlSite.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(   
	/* [unique][in] */ const GUID __RPC_FAR *pguidCmdGroup,   
	/* [in] */ ULONG cCmds,   
	/* [out][in][size_is] */ OLECMD __RPC_FAR prgCmds[ ],   
	/* [unique][out][in] */ 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.


再次感谢thinkingfor

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值