You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FireMonkey(Delphi10.3.3)TWebBrowser拦截导航并执行JS的方案求助

解决FireMonkey TWebBrowser链接拦截问题(不用CEF4)

嘿,我之前也碰到过一模一样的情况——用LoadFromStrings加载动态HTML时,DocumentWebBrowserShouldStartLoadWithRequest完全没反应,后面调用Stop之类的方法也拦不住导航。下面给你几个不用CEF4就能搞定的方案,按省心程度从高到低排:

1. 从源头修改HTML,彻底避免导航触发

这是最省事的办法,直接把目标链接改成不会触发导航的形式,同时绑定自定义点击逻辑。你可以在加载HTML前用正则替换所有符合格式的链接:

Delphi代码示例(修改HTML字符串)

uses System.RegularExpressions;

// 假设原始HTML存在browser_html变量中
browser_html := TRegEx.Replace(browser_html, 
  '<a id="position_(\d+)" class="cdimmed" href="pos_\1">(.*?)</a>',
  '<a id="position_$1" class="cdimmed" href="javascript:void(0)" onclick="handlePositionClick($1)">$2</a>');

// 加载修改后的HTML
DocumentWebBrowser.LoadFromStrings(browser_html, '');

然后在你的HTML里添加对应的JavaScript函数(可以直接写在HTML头部,或者后续通过Delphi注入):

<script>
function handlePositionClick(posId) {
  // 这里写你需要执行的JS逻辑
  console.log('点击了位置ID:' + posId);
  // 如果需要和Delphi交互,还可以调用暴露给JS的Delphi方法
}
</script>

这种方式完全不会触发浏览器的导航行为,自然也就不用纠结那些拦截事件了。

2. 页面加载完成后注入JS拦截点击

如果没法提前修改HTML字符串,那就等页面加载完成后,用JavaScript给所有目标链接绑定点击拦截逻辑:

Delphi代码示例

procedure TForm1.DocumentWebBrowserDocumentComplete(Sender: TObject);
var
  JSCode: string;
begin
  JSCode := 
    '// 获取所有符合条件的链接' +
    'var targetLinks = document.querySelectorAll(''a[id^="position_"].cdimmed'');' +
    'for(var i = 0; i < targetLinks.length; i++) {' +
    '  targetLinks[i].addEventListener(''click'', function(e) {' +
    '    e.preventDefault(); // 阻止默认导航行为' +
    '    var posId = this.id.split(''_'')[1];' +
    '    // 执行你的自定义JS逻辑' +
    '    console.log(''处理位置:'' + posId);' +
    '  });' +
    '}';
  
  // 执行注入的JavaScript代码
  DocumentWebBrowser.EvaluateJavaScript(JSCode, nil);
end;

注意点:

  • 一定要在OnDocumentComplete事件里执行这段代码,此时页面DOM已经完全加载,才能正确找到所有链接元素。
  • 如果后续HTML有动态更新(比如新增了链接),需要在更新后重新执行这段JS代码。

3. 用自定义协议触发拦截事件

如果你坚持想用ShouldStartLoadWithRequest事件拦截,那得给链接改成自定义协议格式——因为LoadFromStrings加载的本地内容,只有当链接指向外部资源或自定义协议时,才会触发这个事件:

步骤1:修改HTML链接的href为自定义协议

browser_html := TRegEx.Replace(browser_html, 
  '<a id="position_(\d+)" class="cdimmed" href="pos_\1">(.*?)</a>',
  '<a id="position_$1" class="cdimmed" href="myapp://pos_$1">$2</a>');

步骤2:处理ShouldStartLoadWithRequest事件

procedure TForm1.DocumentWebBrowserShouldStartLoadWithRequest(Sender: TObject;
  const URL: string; NavigationType: TWebBrowserNavigationType; var Result: Boolean);
begin
  if Pos('myapp://pos_', URL) > 0 then
  begin
    // 阻止导航
    Result := False;
    // 提取位置ID
    var posId := Copy(URL, Length('myapp://pos_') + 1, MaxInt);
    // 执行你的逻辑,比如调用JS函数
    DocumentWebBrowser.EvaluateJavaScript('handlePositionClick(' + posId + ')', nil);
  end;
end;

这个方法适合没法提前修改点击逻辑,但又想用事件拦截的场景。


内容的提问来源于stack exchange,提问作者Miguel E

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 14:47:39