我在使用 TChromium (DCEF1) 的 OnLoadEnd 事件时遇到问题。
我有一个表格,上面有一个TButton和一个TChromium。
按钮的 OnClick 事件调用列出已加载页面窗体的函数。如果我等待页面加载完成,然后单击按钮,则此功能工作正常;但是如果我从 TChromium OnLoadEnd 事件处理程序调用此函数,则永远不会调用回调函数,因此,我得到一个空列表。
按钮代码(将注释读入代码):
procedure TForm2.Button3Click(Sender: TObject);
var
Q: TWebChromium;
begin
Q := TWebChromium.Create(Chromium1); // <- class to access DOM
Q.WebFormNames; // <- method to get forms name
ShowMessage(Q.Forms.Text); // <- show forms
end;
加载结束代码:
procedure TForm2.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; httpStatusCode: Integer; out Result: Boolean);
begin
if (browser <> nil) and (browser.GetWindowHandle = TChromium(Sender).BrowserHandle) and ((frame = nil) or (frame.IsMain)) then
begin
Button3Click(nil);
end;
end;
获取表单名称的方法代码(将注释读入代码):
procedure TWebChromium.WebFormNames;
var
Finish: Boolean;
EndTime: TTime;
begin
FForms.Clear; // <- property (TStringList)
if not Assigned(FWebBrowser) then // <- FWebBrowser: property that contain the TChromium
raise Exception.Create('WebBrowser not assigned');
if not (FWebBrowser is TChromium) then
raise Exception.Create('The WebBrowser property is not a TChromium.');
Finish := False;
TChromium(FWebBrowser).Browser.MainFrame.VisitDomProc(
procedure (const doc: ICefDomDocument) // <- this procedure is not called if this method is called from OnLoadEnd event
begin
FForms.CommaText := GetFormsName(doc.Body);
Finish := True;
end
);
EndTime := IncSecond(Time, 4);
repeat Application.ProcessMessages until Finish or (Time > EndTime);
if Time > EndTime then
raise Exception.Create('Time out');
end;
嗯,我知道这个问题是几年前问过的,但我对 TChromium 很陌生。这是我从以前的提案中提出的解决方案。通常,TChromium 会发送 Event OnLoadEnd,但在加载之前发送,例如 JS。所以我解决了这个问题,以便在 OnLoadEnd 过程中等待一段时间,以防任何脚本仍在加载,然后发送通知,如下所示
procedure TForm1.OnLoadEndCust(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; httpStatusCode: Integer);
var EndTime: TTime;
begin
EndTime := IncSecond(Now, 2);
repeat Application.ProcessMessages until (Now > EndTime);
end;
到目前为止 - 这就足够了,但是还有其他更好或更优雅的解决方案吗?
为什么我们应该在上面的代码中使用VisitDomProc?当我们从OnLoadEnd调用它时,它似乎是不必要的。你们觉得呢?
我同时使用了DCEF 1和DCEF 3,如果你可以切换到3,你应该,很多改进。
以下是DCEF 3的链接:https://code.google.com/p/dcef3/
您拥有的方法绝对应该有效:
procedure TMainForm.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; httpStatusCode: Integer);
begin
if IsMain(browser, frame) then begin
// main window done from here on in
end;
end;
如果没有,它可以是 2 件事中的 1 件,
您的表单数据被搞砸了,不知何故不再附加事件,请仔细检查组件中的事件属性。
您的构建有问题,请尝试在示例目录中运行 GUIClient,它具有相同的事件并且应该被触发,如果它不尝试查找另一个构建(最好是我之前链接到的 DCEF3 版本)
祝你好运
我遇到了同样的问题,我注意到当httpStatusCode为200时页面已完全加载。为了方便起见,我实现了一个布尔变量。
TForm2 = class(TForm)
procedure Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; httpStatusCode: Integer);
procedure Chromium1LoadStart(Sender: TObject; const browser: ICefBrowser;
private
{ Private declarations }
IsFullyDisplayed : Boolean;
end;
procedure TForm2.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame; httpStatusCode: Integer);
begin
if frame = nil then
exit;
if httpStatusCode=200 then
begin
IsFullyDisplayed:=True;
end;
end;
procedure TForm2.Chromium1LoadStart(Sender: TObject; const browser: ICefBrowser;
const frame: ICefFrame);
begin
IsFullyDisplayed := False;
end;