昨日 aq に促されて、ここから TGeckoBrowser に慣れようとしています: http://sourceforge.net/p/d-gecko/wiki/Home。
(注: Mozilla XulRunner パッケージをインストールする必要があります)
WinXP の時代に最後に試してから、状況が少し後退したようです。URL に移動するための最小限の D7 プロジェクトで、以前に見たことを思い出せないエラーが発生しています。以下に私のコードを含めました。これらは、www.google.com、news.bbc.co.uk、そしてもちろんここなどのサイトに移動するときに遭遇したエラーです。
- 最初の例外 - 「Safecall メソッドの例外」 - は、フォームが最初に表示されたときに発生し、どこにでもナビゲートする前に発生します。TApplication.OnException ハンドラの形で回避策があります。
私の質問は次のとおりです。a) そもそもそれを回避する方法を知っている人はいますか、または b) TApplication.Exception ハンドラーを設定するよりもきちんとキャッチする方法はありますか? (アプリケーション全体のハンドラーをまったく持たずに、ユーザーに例外が表示されるのを避けるために1つ持つことを意味します)。
この例外は、次のコードで発生します。
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 に応じて「無効な浮動小数点演算」が 1 回以上発生します。
2.b ここでも、URL によっては、「モジュール js3250.dll のアドレス 556318B3 でアクセス違反が発生しました。アドレス 00000008 の読み取り」が表示されます。または類似。一部のページでは、数秒ごとに発生します (ページ内の JS タイマー コードに感謝します)。
2a と 2b は以下の TForm1.OnCreate で Set8087CW を呼び出すことで回避されますが、主に誰かがそれらと 1 を何らかのシステム上の問題の兆候として認識した場合に言及していますが、Google は他の人のためにこの q を見つけるでしょうそんな症状に陥った方。
q 1b) に戻ると、StdWndProc-> TWinControl.MainWndProc->[...]->TCustomGeckoBrowser.Paint から "Exception in Safecall method" が発生します。TApplication.OnException ハンドラーを使用する代わりに、ハンドラーを配置して TCustomGeckoBrowser.Paint のコードを変更しないように、呼び出しチェーンのさらに上で例外をキャッチする方法はありますか?
更新: SafeCall に関する次のドキュメントにコメントが寄せられました。
ESafecallException は、safecall エラー ハンドラが設定されておらず、safecall ルーチンが 0 以外の HResult を返す場合、または safecall エラー ハンドラが例外を発生させない場合に発生します。この例外が発生した場合、Comobj ユニットがアプリケーションの uses リストにないか (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;