昨天在 aq 的提示下,我试图从这里重新熟悉 TGeckoBrowser:http: //sourceforge.net/p/d-gecko/wiki/Home。
(注:需要安装 Mozilla XulRunner 包)
自从我上次在 WinXP 时代尝试以来,事情似乎有点倒退了,因为用最小的 D7 项目导航到 URL,我遇到了我不记得以前见过的错误。我在下面包含了我的代码。这些是我在导航到 www.google.com、news.bbc.co.uk 等网站时遇到的错误,当然还有这里。
- 第一个异常 - “Safecall 方法中的异常” - 在我的表单首次显示时发生,然后在任何地方导航。我有一个 TApplication.OnException 处理程序形式的解决方法。
我的问题是:a) 有没有人知道如何首先避免它或 b) 有没有比设置 TApplication.Exception 处理程序更整洁的方法来捕获它,这对我来说总是有点承认失败(我的意思是让用户避免看到异常,根本没有应用程序范围的处理程序)。
此异常发生在此代码中:
procedure TCustomGeckoBrowser.Paint;
var
rc: TRect;
baseWin: nsIBaseWindow;
begin
if csDesigning in ComponentState then
begin
rc := ClientRect;
Canvas.FillRect(rc);
end else
begin
baseWin := FWebBrowser as nsIBaseWindow;
baseWin.Repaint(True);
end;
inherited;
end;
在对 baseWin.Repaint 的调用中,因此推测它可能来自接口的另一侧。我只在第一次调用 .Paint 时得到它。我注意到在这一点上,baseWin 为 GetVisibility 返回 False,因此我的 TForm1.Loaded 中的实验代码,看看这是否会避免它。它不是。
2.a 调用 GeckoBrowser1.LoadURI 后,根据正在加载的 URL,我得到一次或多次“无效浮点操作”。
2.b 同样,根据 URL,我得到:“模块 js3250.dll 中地址 556318B3 的访问冲突。读取地址 00000008。” 或类似的。在某些页面上,它每隔几秒钟发生一次(感谢我想象页面中的一些 JS 计时器代码)。
通过在下面的 TForm1.OnCreate 中调用 Set8087CW 可以避免 2a 和 2b,但我提到它们主要是为了以防有人将它们和 1 一起识别为某种系统性问题的症状,但谷歌也会为其他人找到这个 q谁遇到了这些症状。
回到我的问题 1b),“Safecall 方法中的异常”发生在 StdWndProc-> TWinControl.MainWndProc->[...]->TCustomGeckoBrowser.Paint。除了使用 TApplication.OnException 处理程序之外,有没有办法在调用链中进一步捕获异常,以避免通过在其中放置处理程序来修改 TCustomGeckoBrowser.Paint 的代码?
更新:一条评论提请我注意与 SafeCall 相关的此文档:
当安全调用错误处理程序尚未设置且安全调用例程返回非 0 HResult,或者安全调用错误处理程序未引发异常时,将引发 ESafecallException。如果发生此异常,则 Comobj 单元可能从应用程序的使用列表 (Delphi) 中丢失或未包含在项目源文件 (C++) 中。您可能需要考虑从导致异常的例程中删除 safecall 调用约定。
GeckoBrowser 源带有一个单元 BrowserSupports,它看起来像一个类型库导入单元,只是它似乎是手动准备的。它包含一个接口,该接口包括产生 SafeCall 异常的 Repaint 方法。
nsIBaseWindow = interface(nsISupports)
['{046bc8a0-8015-11d3-af70-00a024ffc08c}']
procedure InitWindow(parentNativeWindow: nativeWindow; parentWidget: nsIWidget; x: PRInt32; y: PRInt32; cx: PRInt32; cy: PRInt32); safecall;
procedure Create(); safecall;
procedure Destroy(); safecall;
[...]
procedure Repaint(force: PRBool); safecall;
[...]
end;
按照 quoyed 文档中的建议,我在 Repaint 成员(但仅限于该成员)上将“safecall”更改为 StdCall,并且,突然!异常停止发生。如果它在接下来的几天内没有再次出现,我会将其作为答案发布,除非有人提出更好的答案。
我的项目代码:
uses
BrowserSupports;
procedure TForm1.FormCreate(Sender: TObject);
begin
Set8087CW($133F);
Application.OnException := HandleException;
end;
procedure TForm1.HandleException(Sender: TObject; E: Exception);
begin
Inc(Errors);
Caption := Format('Errors %d, msg: %s', [Errors, E.Message]);
Screen.Cursor := crDefault;
end;
type
TMyGeckoBrowser = class(TGeckoBrowser);
procedure TForm1.Loaded;
begin
inherited;
GeckoBrowser1.HandleNeeded;
(TMyGeckoBrowser(GeckoBrowser1).WebBrowser as nsIBaseWindow).SetVisibility(True);
end;
procedure TForm1.btnLoadUrlClick(Sender: TObject);
begin
try
GeckoBrowser1.LoadURI(edUrl.Text);
except
end;
end;