【问题标题】:How do I make TWebBrowser keep running JavaScript after an error?出错后如何让 TWebBrowser 继续运行 JavaScript?
【发布时间】:2011-12-19 19:49:30
【问题描述】:

我在 Delphi 2010 上的 WebBrowser 中处理 javascript 错误时遇到了一些问题。

我正在使用启用了静默属性的 WebBrowser。似乎没问题,但是在带有错误脚本的站点上存在一个问题:错误未执行后似乎是脚本的一部分。部分脚本的结果与 IE 略有不同。

您知道如何解决这个问题吗?

【问题讨论】:

    标签: javascript delphi browser


    【解决方案1】:

    您可以使用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;
    

    【讨论】:

    • 此方法还抑制所有 javascript 弹出窗口。
    • 您是否有任何这样的示例页面?请参阅this 文章。您确定在显示弹出窗口之前没有错误吗?恕我直言,它应该只抑制错误,但我可以看看......
    • @TipTop,一般来说,代码与 JavaScript 调用的弹出窗口无关。如果您确实对代码有问题,我认为默认返回值不应该是 S_OK,而是 OLECMDERR_E_NOTSUPPORTED。
    • @TLama,这两个方法的默认返回值应该是 OLECMDERR_E_NOTSUPPORTED。相信我。
    【解决方案2】:

    这是我的实施建议。

    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,否则会出现异常。
    • 请检查您的代码并确保您在显示之前了解您所说的内容,以便将我的帖子与另一篇帖子进行比较,我有一些有价值的东西。您在哪里找到 @987654323 @value 是布尔值?你怎么知道当前执行的命令的结果是布尔值并且意味着 True to execute ?接下来,您正在混合结果值,我之前告诉过您,IOleCommandTarget::QueryStatus 没有OLECMDERR_E_NOTSUPPORTED 结果值...接下来,您为什么要测试指向指针的事件处理程序?只需测试if Assigned(OnNotifyScriptError) then OnNotifyScriptError(...)
    • ...看看VCL是怎么写的,它是你能得到的最好的源码。与IsEqualGUID 的行我根本不明白。我个人的结论是,如果您认真对待,那么请尝试更仔细地阅读文档(如果您是从另一个非官方文档中获得的,那么就离开吧)。如果有人评论我的帖子并告诉我自己的意见,我很高兴,但不是这样。如果您只需要查看自己的代码,那么您可以给我留言,我可以帮助您,例如通过电子邮件。
    • (1) nCmdID 不是唯一的。不同的命令组可能具有相同的 nCmdID。这就是为什么我们必须首先使用 IsEqualGUID() 检测命令组的原因。 (2) vaOut 是一个 OleVariant。它可以是字符串、布尔值、整数或其他。 (这里有一些例子:msdn.microsoft.com/en-us/library/aa752044(v=vs.85))它取决于命令本身,不幸的是,vaOut 的类型和值通常没有正式记录。我已经验证了命令,vaOut 代表布尔值。
    猜你喜欢
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    相关资源
    最近更新 更多