2011-12-19 24 views
9

Delphi 2010 WebBrowserでjavascriptエラー処理に問題があります。エラーの後にJavaScriptを実行し続けるにはどうすればよいですか?

有効なサイレントプロパティでWebBrowserを使用しています。 OKと思われますが、バグのあるサイトには1つの問題があります。エラーが発生してもスクリプトの一部のように見えます。いくつかのスクリプトの結果はIEと少し異なります。

この問題をどのように解決できますか?

答えて

12

IOleCommandTargetを使用し、そのIOleCommandTarget.Execメソッドでは、OLECMDID_SHOWSCRIPTERRORコマンドをキャッチすることができます。

次の例では介在クラスを使用していますので、このコードをユニットに配置すると、フォーム上のWebブラウザまたはこのユニットで動的に作成されたブラウザのみがこの動作を行います。

uses 
    SHDocVw, ActiveX; 

type 
    TWebBrowser = class(SHDocVw.TWebBrowser, IOleCommandTarget) 
    private 
    function QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; prgCmds: POleCmd; 
     CmdText: POleCmdText): HRESULT; stdcall; 
    function Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
     const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
    end; 

implementation 

function TWebBrowser.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; 
    prgCmds: POleCmd; CmdText: POleCmdText): HRESULT; stdcall; 
begin 
    Result := S_OK; 
end; 

function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
    const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
begin 
    // presume that all commands can be executed; for list of available commands 
    // see SHDocVw.pas unit, using this event you can suppress or create custom 
    // events for more than just script error dialogs, there are commands like 
    // undo, redo, refresh, open, save, print etc. etc. 
    // be careful, because not all command results are meaningful, like the one 
    // with script error message boxes, I would expect that if you return S_OK, 
    // the error dialog will be displayed, but it's vice-versa 
    Result := S_OK; 

    // there's a script error in the currently executed script, so 
    if nCmdID = OLECMDID_SHOWSCRIPTERROR then 
    begin 
    // if you return S_FALSE, the script error dialog is shown 
    Result := S_FALSE; 
    // if you return S_OK, the script error dialog is suppressed 
    Result := S_OK; 
    end; 
end; 
+0

このメソッドは、すべてのjavascriptポップアップを抑制します。 – TipTop

+0

このように動作するサンプルページはありますか? ['this'](http://support.microsoft.com/kb/261003)の記事を参照してください。ポップアップが表示される前にエラーがないことは確かですか? IMHOはエラーだけを抑制する必要がありますが、私は一見することができます... – TLama

+0

@TipTopは、一般的に言えば、コードはJavaScript呼び出しのポップアップとは関係ありません。コードに問題がある場合は、デフォルトの戻り値はS_OKではなく、OLECMDERR_E_NOTSUPPORTEDであるべきだと思います。 – stanleyxu2005

4

これは私の推奨する実装です。

uses 
    SHDocVw, ActiveX; 

type 
    TWebBrowser = class(SHDocVw.TWebBrowser, IOleCommandTarget) 
    private 
    function QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; prgCmds: POleCmd; 
     CmdText: POleCmdText): HRESULT; stdcall; 
    function Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
     const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
    end; 

implementation 

function TWebBrowser.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal; 
    prgCmds: POleCmd; CmdText: POleCmdText): HRESULT; stdcall; 
begin 
    // MSDN notes that a command target must implement this function; E_NOTIMPL is not a 
    // valid return value. Be careful to return S_OK, because we notice that context menu 
    // of Web page "Add to Favorites..." becomes disabled. Another MSDN document shows an 
    // example with default return value OLECMDERR_E_NOTSUPPORTED. 
    // http://msdn.microsoft.com/en-us/library/bb165923(v=vs.80).aspx 
    Result := OLECMDERR_E_NOTSUPPORTED; 
end; 

function TWebBrowser.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD; 
    const vaIn: OleVariant; var vaOut: OleVariant): HRESULT; stdcall; 
var 
    ShowDialog, InterpretScript: Boolean; 
begin 
    if CmdGroup = nil then 
    begin 
    Result := OLECMDERR_E_UNKNOWNGROUP; 
    Exit; 
    end; 

    // MSDN notes that a command target must implement this function; E_NOTIMPL is not a 
    // valid return value. Be careful to return S_OK, because we notice some unhandled 
    // commands behave unexpected with S_OK. We assumed that a return value 
    // OLECMDERR_E_NOTSUPPORTED means to use the default behavior. 
    Result := OLECMDERR_E_NOTSUPPORTED; 

    if IsEqualGUID(CmdGroup^, CGID_DocHostCommandHandler) then 
    begin 
    // there's a script error in the currently executed script, so 
    if nCmdID = OLECMDID_SHOWSCRIPTERROR then 
    begin 
     ShowDialog := True; 
     InterpretScript := False; 

     // Implements an event if you want, so that your application is able to choose the way of handling script errors at runtime. 
     if Assigned(OnNotifyScriptError) then 
     OnNotifyScriptError(Self, ShowDialog, InterpretScript); 

     if ShowDialog then 
     Result := S_FALSE 
     else 
     Result := S_OK; 
     vaOut := InterpretScript; // Without setting the variable to true, further script execution will be cancelled. 
    end; 
    end; 
end; 
+0

"vaOut:= InterpretScript;"少なくともこれは貴重なヒントです。私はmsdnを何度も読んでいます、私はあなたに同意します、これらの戻り値は* S_OKでなければなりません。しかし、実際のアプリケーションでの私の経験によると、OLECMDERR_E_NOTSUPPORTEDに設定する必要があります。そうしないと、予期しない動作が発生します。 – stanleyxu2005

+0

あなたのコードを見直し、私の投稿を他のものと比較するためにあなたが言う前にあなたが言うことを知っていることを確認してください、私は何か貴重なものを持っています*あなたは 'vaOut'現在実行されているコマンドの結果がブール値になり、実行するにはTrueを意味することをどのように知っていますか?次に、結果値を混合しています。私は前に言ったことがあります。IOleCommandTarget :: QueryStatusには結果値OLECMDERR_E_NOTSUPPORTEDはありません。次に、ポインタへのポインタのイベントハンドラをテストしていますか? 'On Assignment(OnNotifyScriptError)then OnNotifyScriptError(...)'をテストするだけです。 – TLama

+0

... VCLがどのように書かれているかを見てください。 'IsEqualGUID'の行はまったく得られません。私の個人的な結論は、もしあなたがこの文書をもっと慎重に読んでみてください。誰かが自分の投稿を見直して私に自分の意見を伝えればうれしいですが、そうではありません。あなた自身のコードを見直す必要がある場合は、私にコメントを残しておいてください。電子メールを介して。 – TLama

関連する問題