我在使用Delphi 2010的WebBrowser中的javascript錯誤處理方面遇到了一些麻煩。如何讓TWebBrowser在發生錯誤後繼續運行JavaScript?
我使用WebBrowser並啓用了無聲屬性。似乎沒問題,但在有錯誤腳本的網站上有一個問題:在錯誤未執行後,它好像是腳本的一部分。某些腳本的結果與IE略有不同。
你有什麼想法如何解決這個問題?
我在使用Delphi 2010的WebBrowser中的javascript錯誤處理方面遇到了一些麻煩。如何讓TWebBrowser在發生錯誤後繼續運行JavaScript?
我使用WebBrowser並啓用了無聲屬性。似乎沒問題,但在有錯誤腳本的網站上有一個問題:在錯誤未執行後,它好像是腳本的一部分。某些腳本的結果與IE略有不同。
你有什麼想法如何解決這個問題?
您可以使用IOleCommandTarget
並在其IOleCommandTarget.Exec
方法中捕獲OLECMDID_SHOWSCRIPTERROR
命令。
在以下示例中,我使用了插入類,因此如果將此代碼放入單元中,則只有表單上的那些Web瀏覽器或動態創建的那些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;
這是我的實施建議。
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;
「vaOut:= InterpretScript;」至少這是一個有價值的提示。我多次閱讀msdn,我同意你的看法,這些返回值*應該*爲S_OK。但根據我在實際應用中的經驗,我必須將它們設置爲OLECMDERR_E_NOTSUPPORTED,否則它的行爲會出乎意料。 – stanleyxu2005 2012-05-21 15:49:34
請檢查你的代碼,並確保你知道你說什麼之前,你展現*比較我的文章與另一個,我有一些有價值的。*你在哪裏發現'vaOut'值是布爾值?你怎麼知道當前執行的命令的結果是布爾值,並且意味着要執行?接下來,你混合了結果值,我以前告訴過你,IOleCommandTarget :: QueryStatus沒有OLECMDERR_E_NOTSUPPORTED結果值...接下來,你爲什麼要測試指向指針的事件處理程序?只要測試'如果分配(OnNotifyScriptError)然後OnNotifyScriptError(...)' – TLama 2012-05-21 19:11:52
...看看如何編寫VCL,這是你可以得到的最好的來源。帶有'IsEqualGUID'的行我根本沒有得到。我個人的結論是,如果你認真對待這個問題,那麼應該仔細閱讀文檔(如果你從另一個非官方的文檔中得到它,那麼就離開它)。我很高興如果有人審查我的帖子,並告訴我自己的意見,但不是這樣。如果您只需要查看自己的代碼,那麼您可以給我留言,我可以幫助您解決問題,例如通過電子郵件。 – TLama 2012-05-21 19:29:19
該方法還抑制所有JavaScript彈出窗口。 – TipTop 2012-04-24 11:47:49
你有任何樣本頁面的行爲是這樣嗎?請參閱['this'](http://support.microsoft.com/kb/261003)文章。在彈出窗口顯示之前,你確定沒有錯誤嗎?恕我直言,它應該只壓制錯誤,但我可以看看... – TLama 2012-04-24 11:52:43
@TipTop,一般來說,代碼與JavaScript調用彈出窗口無關。如果您確實遇到了代碼問題,我認爲默認返回值不應該是S_OK,而應該是OLECMDERR_E_NOTSUPPORTED。 – stanleyxu2005 2012-05-21 14:45:09