我正在尝试使用以下代码枚举DOM节点(在XE2下)。
我从SO中给出的答案中借用了大部分内容,但出于某种原因,它没有做任何事情。
IOW,ProcessDOM()永远不会被调用。
而且,我在我的智慧结束。
有人能告诉我这里我做错了什么。
提前致谢。
procedure ProcessNode(ANode: ICefDomNode);
var
Node1: ICefDomNode;
begin
if Assigned(ANode) then begin
Node1 := ANode.FirstChild;
while Assigned(Node1) do begin
{Do stuff with node}
ProcessNode(Node1);
Node1 := Node1.NextSibling;
end;
end;
end;
procedure ProcessDOM(const ADocument: ICefDomDocument);
begin
ProcessNode(ADocument.Body);
end;
procedure TMainForm.Chrome1LoadEnd(Sender: TObject; const ABrowser: ICefABrowser; const AFrame: ICefAFrame; AStatus: Integer);
begin
if Assigned(AFrame) then AFrame.VisitDomProc(ProcessDOM);
end;
答案 0 :(得分:1)
我遇到了同样的问题,我使用了dcef3附带的demo guiclient。以下是有效的。
type TCustomRenderProcessHandler = class(TCefRenderProcessHandlerOwn)
protected
function OnProcessMessageReceived(const browser: ICefBrowser; sourceProcess: TCefProcessId; const message: ICefProcessMessage): Boolean; override;
end;
Chromium1.browser.SendProcessMessage(PID_RENDERER, TCefProcessMessageRef.New('visitdom'));
function TCustomRenderProcessHandler.OnProcessMessageReceived(browser: ICefBrowser; sourceProcess: TCefProcessId; message: ICefProcessMessage): Boolean;
begin
if (message.Name = 'visitdom') then begin
browser.MainFrame.VisitDomProc(
procedure(const doc: ICefDomDocument)
begin
ProcessNode(Doc.Body);
end);
Result := True;
end;
end;
initialization
CefRenderProcessHandler := TCustomRenderProcessHandler.Create;
答案 1 :(得分:0)
您需要向处理程序添加一个过程。 过程ProcessNode(ANode:ICefDomNode);
阅读本文:1
答案 2 :(得分:0)
正如此blog指出的那样,访问呈现页面的DOM时的主要困难在于,您只能在与该页面的关联呈现器相同的过程中执行此操作。
您无法从浏览器线程访问dom,您必须在渲染器线程中执行此操作。
首先,将一条消息(如visitdom)从浏览器进程转发到呈现过程
procedure TMainForm.crmLoadEnd(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; httpStatusCode: Integer);
var
msg : ICefProcessMessage;
begin
if IsMain(browser, frame) then
FLoading := False;
msg := TCefProcessMessageRef.New('visitdom');
browser.SendProcessMessage(PID_RENDERER, msg);
end;
其次,创建一个TCustomRenderProcessHandler来处理消息,将结果发送回浏览器进程。
function TCustomRenderProcessHandler.OnProcessMessageReceived(
const browser: ICefBrowser; sourceProcess: TCefProcessId;
const message: ICefProcessMessage): Boolean;
begin
Result := False;
if (message.Name = 'visitdom') then
begin
browser.MainFrame.VisitDomProc(
procedure(const doc: ICefDomDocument)
function ProcessNode(ANode: ICefDomNode) : String;
var
Node: ICefDomNode;
begin
Result := 'Not Found';
if Assigned(ANode) then
begin
Node := ANode.FirstChild;
while Assigned(Node) do
begin
if Node.ElementTagName='DIV' then
begin
if Node.GetElementAttribute('class')='tv-panels' then
begin
Result := 'Found';
Exit;
end;
end;
ProcessNode(Node);
Node := Node.NextSibling;
end;
end;
end;
var msg : ICefProcessMessage;
begin
msg := TCefProcessMessageRef.New('visitdom');
msg.ArgumentList.SetString(0, processNode(doc.Body));
browser.SendProcessMessage(PID_BROWSER, msg);
end);
Result := True;
end;
end;
第三,在浏览器进程中,创建一个处理程序来处理从渲染过程发回的消息。
procedure TMainForm.crmProcessMessageReceived(Sender: TObject;
const browser: ICefBrowser; sourceProcess: TCefProcessId;
const message: ICefProcessMessage; out Result: Boolean);
begin
Result := False;
if (message.Name = 'visitdom') then
begin
StatusBar.SimpleText := message.ArgumentList.GetString(0);
Result := True;
end;
end;
小心,在调试时,在渲染过程中放置一个断点永远不会工作。它永远不会到达那里。