最近一个项目中要在对话框上使用WebBrowser控件进行页面浏览,但在开发过程中发现WebBrowser控件会在浏览一些页面的时候出现JavaScript脚本错误,严重影响用户体验,而在IE和其他第三方浏览器中均没有这个现象。于是搜索一下发现原来可以通过下面的代码禁止这个错误提示:
- m_WebBrowser.put_Silent(TRUE);//禁止脚本错误提示
效果非常好,可以说立竿见影。但是随之问题又来了,在登录银行网站时会出现无法打开网页的错误,原来这个Silent把银行的选择证书窗口也给禁止了.
翻了翻MSDN,发现原来这个参数要么都不禁止,要么都禁止……这显然不符合要求
搜索引擎真是个好东西,就在准备放弃的时候发现这么一篇文章
这会儿真想对着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
(OLECMDID 信息参看下篇博文)
- #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.
再次感谢thinkingfor