Mfc

MFCはCDHtmlDialogを使用して、スクリプトエラーメソッドを無効にします



Mfc Uses Cdhtmldialog Disable Script Error Methods



元の住所: https://blog.csdn.net/zhongbin104/article/details/7555695

WebBrowserコントロール(CDHtmlDialogが自動的にWebBrowserコントロールを作成する)によってロードされたWebページに間違ったJavascriptコードが含まれている場合、コントロールはエラーメッセージプロンプトダイアログボックスをポップアップします。ユーザーエクスペリエンスと比較すると、このようなプロンプトは開発者が望んでいるものではありません。この問題には2つの解決策があります。 1つはエラープロンプトを完全にマスクすることであり、もう1つはエラープロンプトを制御してエラー情報を記録することです。また、エラーが発生した後もJavascriptを実行し続けるかどうかも制御します。



1.すべてのエラーは禁止されています

/ / Forbid script error prompt m_WebBrowser.put_Silent(TRUE)

CDHtmlDialog :: OnInitDialog()のコードでは、最初にWebBrowserコントロールが作成され、次にコントロールのBrowserオブジェクトがm_pBrowserAppに割り当てられます(これはCDHtmlDialogによって行われ、単独で処理する必要はありません)。 WebBrowserのput_Silent関数は、すべてのダイアログを無効にするように公式に述べられていますが、例外は、SSLセキュリティ認証に必要な着信ダイアログに影響を与えないことです。ほとんどの場合、これで問題を解決できます。ずっと前に、put_Silentの呼び出しはまだ非常に小さいですが、ブロックできないjsエラーが表示される(ページにネストが含まれている)という状況に遭遇したことを覚えています。ページが間違っており、ブロックできません。 。他の状況があるかどうかわかりません。今はそのようなウェブページが見つかりません。誰かがこの状況に遭遇した場合は、晴れた年を再訪できるようにURLを送信することをお勧めします。

2.エラープロンプトを制御し、エラーメッセージを記録します。また、エラーが発生した後もJavascriptを実行し続けるかどうかも制御します。

これは、最初の方法よりもはるかに複雑です。つまり、COleControlSiteクラスをカスタマイズし、IOleCommandTargetインターフェイスを実装することです。 IOleCommandTargetインターフェースは、エラー制御の鍵です。エラーが発生すると、このインターフェイスのExec関数がトリガーされ、nCmdIDパラメーターに値が割り当てられます。 OLECMDID_SHOWSCRIPTERRORなので、エラーメッセージを受け取ることができます。



CMyControlSite.h
#pragma once #include 'afxocc.h' #include 'Mshtml.h'// should include this header file #include 'Mshtmhst.h'//This is also 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 //Modify here to false to disable script error prompts 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) / / Can record error information here / / must use SysFreeString to release the memory allocated by SysAllocString, SysAllocString recorded the length of the character in the allocated memory 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) { // continue executing the script on the page (*pvaOut).boolVal = VARIANT_TRUE } else { / / Stop executing scripts in the page (*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 }