【问题标题】:How do I detect a click in TChromium?如何检测 TChromium 中的点击?
【发布时间】:2014-02-21 04:46:46
【问题描述】:

我的 Delphi 应用程序中有一个 TChromium 控件,在我显示的页面上,有一个链接可以最小化该应用程序。目前,我通过检测地址更改来检测用户何时点击该链接:

procedure TForm1.Chromium1AddressChange(Sender: TObject;const browser: ICefBrowser; const frame: ICefFrame; const url: ustring);
begin
if (url = 'file:///data/exiting.exit') then
Form1.Close;

if (url = 'file:///data/minimize.min') then
Application.Minimize;

end;

但是,副作用是浏览器的 URL 发生了变化,这是我不想要的。如何检测用户何时点击链接而不更改 URL?

【问题讨论】:

  • 我不明白。您可以随时拨打Application.Minimize。您无需等到有人在地址栏中键入一个神奇的 URL。你真正的问题是什么?
  • Application.Minimize 在有人按下 html 文档中的最小化按钮时调用。最小化按钮 - 。当我按下此按钮时,我的应用程序最小化并且 url 更改为 file:///data/minimize.min。
  • 我明白了。您问如何最小化程序,但这并不是您真正想知道的;你已经知道该怎么做了。您真正想要的是一种破坏性较小的方法来检测浏览器控件中的单击事件。我已经相应地编辑了您的问题。
  • 好的,谢谢!对不起我的英语!

标签: delphi delphi-7 chromium-embedded


【解决方案1】:

如果我没看错你的问题,你的 HTML 文档中有这样的链接:

<a href="minimize.min">Minimize</a>

并且您想在单击此链接时在您的应用程序中执行某些操作,但您不想导航到该链接,因为它只是一个仅用于识别操作的假链接。好吧,OnAddressChange 是一个错误的事件,因为当帧的地址发生变化时,它被显示处理程序触发。因此,从那里取消导航到那个假网站已经太迟了。在 DCEF 1 中,您可以为 OnBeforeBrowse 编写处理程序,但即使这样也不是“如此干净”的解决方案,因为您必须解析框架导航到的 URL。

正确的方法是离开虚假站点导航并使用 DOM 事件侦听器。然后,您使用什么元素或事件进行交互并不重要。让我们拥有这个简约的 HTML 文档:

<html>
  <body>
     <a id="minimize" href="">Minimize</a>
  </body>
</html>

如您所见,它无法导航到任何地方,但仍会呈现为链接。它还有自己独特的id 标识符,用于 DOM 探索识别。现在让我们为minimize 元素添加click 事件的侦听器。此绑定在框架加载后立即完成,通过触发OnLoadEnd 事件来报告。在那里我们将探索 DOM 树,找到我们的 minimize 元素并将 click 事件监听器附加到它:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, cefvcl, ceflib;

type
  TForm1 = class(TForm)
    Chromium1: TChromium;
    procedure FormCreate(Sender: TObject);
    procedure Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
      const frame: ICefFrame; httpStatusCode: Integer; out Result: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  Chromium1.Load('C:\File.html');
end;

procedure MinimizeClickEvent(const AEvent: ICefDomEvent);
begin
  ShowMessage('Here the application can be minimized.');
end;

procedure OnExploreDOM(const ADocument: ICefDomDocument);
var
  DOMNode: ICefDomNode;
begin
  // here we attempt to find our "minimize" element
  DOMNode := ADocument.GetElementById('minimize');
  // and if we find it, we attach to its click event our MinimizeClickEvent
  // procedure so whenever the element will be clicked, that procedure will
  // execute
  if Assigned(DOMNode) then
    DOMNode.AddEventListenerProc('click', True, MinimizeClickEvent);
end;

procedure TForm1.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
  const frame: ICefFrame; httpStatusCode: Integer; out Result: Boolean);
begin
  if Assigned(frame) then
    frame.VisitDomProc(OnExploreDOM);
end;

end.

通过对代码或 HTML 文档的微小更改,您可以监听您选择的任何事件或元素,因此您可以拥有例如您网站上的一个按钮:

<html>
  <body>
     <button id="minimize" type="button">Minimize</button>
  </body>
</html>

当然,您可以为任意数量的元素附加事件侦听器。

【讨论】:

  • OnExploreDOM 未执行。我在 DOMNode 之后通过 put ShowMessage('OnExploreDOM') 进行检查:= Document.GetElementById('minimize');
  • 问题很可能出在您使用的 DCEF 版本中。我记得其中一些(更新的版本)在根本无法探索 DOM 时出现错误。那是known issue。使用此技术的唯一解决方案是使用不同的版本(旧版本的 DCEF1 可以使用此功能,或者现在(已修复)在基于 DCEF 3 的新平台上)。
  • 我使用 Delphi 7 和 CEF3
  • @TLama 可以点击ICefDomNode 吗?我们可以编辑值和属性,但我们可以点击吗?
  • @TLama:此答案不适用于 dcef3(dcef3 中不再存在 AddEventListenerProc)。 dcef3 有解决方案吗?谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多