昨天在这里提示q,我正在尝试重新熟悉TGeckoBrowser 从这里:http://sourceforge.net/p/d-gecko/wiki/Home。
(Nb:需要安装Mozilla XulRunner软件包)
自从我上次尝试在WinXP时代以来,事情似乎已经向后移动了一点 使用最小的D7项目导航到URL,我收到了我不记得的错误 以前见过。我在下面提供了我的代码。这些是我遇到的错误 导航到www.google.com,news.bbc.co.uk等网站,当然还有这里。
我的q是: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计时器代码)。
2a&在下面的TForm1.OnCreate中调用Set8087CW可以避免使用2b,但我是 提到他们主要是因为有人认出他们和一起作为对症 某种系统性问题,但谷歌也会发现这个问题 对于遇到这些症状的其他人。
回到我的q 1b),“StcWndProc->中发生了”Safecall方法中的异常“。 TWinControl.MainWndProc-> [...] - > TCustomGeckoBrowser.Paint。而不是使用 TApplication.OnException处理程序,有没有办法进一步捕获异常 调用链,以避免修改TCustomGeckoBrowser.Paint的代码 把处理程序放在那里?
更新:评论引起了我对与SafeCall相关的文档的注意:
如果尚未设置safecall错误处理程序并且safecall例程返回非0 HResult,或者safecall错误处理程序未引发异常,则会引发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,并且,presto!,异常停止发生。如果它在接下来的几天内没有重新出现,我会将其作为答案发布,除非有人想出更好的答案。
我的项目代码:
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;
答案 0 :(得分:0)
查看标题,Repaint
的原型实际如下:
HRESULT __stdcall Repaint(PRBool force);
这意味着
procedure Repaint(force: PRBool); safecall;
是一个合理的声明。请记住,safecall
执行参数重写以将COM错误代码转换为异常。
这意味着如果对Repaint
的调用返回指示失败的值,那么safecall机制将表示为异常。如果你想忽略这个特殊的异常,那么在源代码中这样做会更清晰:
try
baseWin.Repaint(True);
except
on EOleException do
; // ignore
end;
如果您希望避免处理异常,那么您可以切换到stdcall
,但您必须记住撤消参数重写。
function Repaint(force: PRBool): HRESULT; stdcall;
现在你可以这样写:
if Failed(baseWin.Repaint(True)) then
; // handle the error if you really wish to, or just ignore it
请注意,Failed
单位定义了ActiveX
。
如果您想进一步排除错误,可以查看错误代码:
var
hres: HRESULT;
....
hres := baseWin.Repaint(True);
// examine hres
或者,如果您要将该函数保留为safecall,则可以从EOleException
实例的ErrorCode
属性中检索错误代码。