8

次のコード (XE2 の下) を使用して DOM ノードを列挙しようとしています。

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;
4

3 に答える 3

1

同じ問題があり、dcef3 に付属のデモ 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;
于 2013-03-09T22:40:40.450 に答える
0

このブログが指摘しているように、レンダリングされたページの 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;

3 番目に、ブラウザ プロセスで、レンダリング プロセスから返されたメッセージを処理するためのハンドラを作成します。

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;

デバッグ中、レンダリング プロセスにブレークポイントを配置しても機能しないことに注意してください。そこに到達することはありません。

于 2016-05-12T03:11:08.930 に答える
0

ハンドラにプロシージャを追加する必要があります。手順 ProcessNode(ANode: ICefDomNode);

これを読む: 1

于 2013-04-14T19:49:20.390 に答える