-1

我正在使用CEF4Delphi项目。

我的目标是加载页面并询问 DOM

我定义了一个事件处理程序Chromium1.OnDocumentAvailable,我可以在其中做

procedure TMiniBrowserFrm.Chromium1DocumentAvailable(Sender: TObject; const aDocument: ICefDomDocument);
begin
  aDocument.GetElementById('client').ElementBounds;
end;

虽然, OnDocumentAvailable永远不会被调用,即使我使用Chromium1.LoadURL(URL).

Chromium 组件加载 URL 后如何访问 DOM?

4

2 回答 2

3

下载最新版本的 CEF4Delphi。它拥有访问 DOM 所需的一切。

查看 uDOMVisitor.pas 文件中的 DOMVisitor_OnDocAvailable 函数(DOMVisitor 演示)。

您提到的旧事件不再存在,DOMVisitor 现在使用带有 TCefFastDomVisitor 的自定义 RenderProcessHandler。

运行 DOMVisitor 并在加载后右键单击网页,然后选择“访问 DOM”。

于 2017-03-22T16:36:15.133 回答
2

我没有使用过 CEF4,但 CEF 3 中包含的演示之一展示了如何使用 Chromium DOM。不幸的是,与 TWebBrowser 不同的是,获取 COM 接口作为进入 DOM 解析器的途径并不是一件简单的事情。因此,您当前的代码不起作用的原因是您没有采取必要的步骤来使用 DOM。

相关的 CEF3 示例是名为“Guiclient”的示例,它使用自定义操作来调用 DOM 处理:

procedure TMainForm.actDomExecute(Sender: TObject);
begin
  crm.browser.SendProcessMessage(PID_RENDERER,
    TCefProcessMessageRef.New('visitdom'));
end;

如您所见,这涉及向 Chromium 的渲染过程发送消息,并使用自定义类来处理它:

TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn)
protected
  procedure OnWebKitInitialized; override;
  function OnProcessMessageReceived(const browser: ICefBrowser; sourceProcess: TCefProcessId;
    const message: ICefProcessMessage): Boolean; override;
end;
[...]
function TCustomRenderProcessHandler.OnProcessMessageReceived(
  const browser: ICefBrowser; sourceProcess: TCefProcessId;
  const message: ICefProcessMessage): Boolean;
begin
//{$IFDEF DELPHI14_UP}
  if (message.Name = 'visitdom') then
    begin
      browser.MainFrame.VisitDomProc(
        procedure(const doc: ICefDomDocument) begin
          doc.Body.AddEventListenerProc('mouseover', True,
            procedure (const event: ICefDomEvent)
            var
              msg: ICefProcessMessage;
            begin
              msg := TCefProcessMessageRef.New('mouseover');
              msg.ArgumentList.SetString(0, getpath(event.Target));
              browser.SendProcessMessage(PID_BROWSER, msg);
            end)
        end);
        Result := True;
    end
  else
//{$ENDIF}
//    Result := False;
end;

procedure TCustomRenderProcessHandler.OnWebKitInitialized;
begin
{$IFDEF DELPHI14_UP}
  TCefRTTIExtension.Register('app', TTestExtension);
{$ENDIF}
end;

因此,与 TWebBrowser 不同的是,您的 DOM 处理代码不会在主线程中执行,您需要在编码中考虑到这一点。

祝你好运。

于 2017-02-28T09:36:22.617 回答