TWebBrowser与MOST html文件崩溃

时间:2016-09-20 15:02:13

标签: delphi twebbrowser

我使用RadPHP 3中提供的uHTMLEdit.pas作为HTML编辑器(基于TWebbrowser)。
当我加载一些HTML文件时程序崩溃。例如,保存此 StackOverflow 页面并将其加载到TWebbrowser中。它会崩溃:

崩溃详情:

Access violation at address 005FAF9B in module 'TestHtmlEditRad.exe'. Read of address 00000000.

Doc.Body.SetAttribute('contentEditable', 'true', 0)行崩溃:

procedure THTMLEdit.EditText(const text: string);
VAR
  Doc: IHTMLDocument2;
  sl: TStringList;
  f: string;
begin
  sl := TStringList.Create;
  TRY
    sl.Text := text;
    f := gettempfile('.html');
    sl.SaveToFile(f);
    wbBrowser.Navigate(f);
    Doc := GetDocument;
    if Doc <> NIL
    then Doc.Body.SetAttribute('contentEditable', 'true', 0);  **Crash HERE**
    DeleteFile(f);
  FINALLY
    FreeAndNil(sl);
  END;
end;

它适用于小型(不那么复杂)的HTML文件。

我的问题是:TWebBrowser崩溃是正常的吗?

要重现,您只需要此代码和uHTMLEdit.pas(已经与Embarcadero RadPHP一起提供)。

unit FormMain;
interface
USES
  Vcl.Controls, Vcl.Forms, Vcl.StdCtrls, uHTMLEdit;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;
var
  Form1: TForm1;

IMPLEMENTATION {$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
VAR debug: string;
begin
  debug:= stringfromfile('test.htm');  // this temporary line of code is mine, for testing. All other code is Embarcadero's
  with THTMLEditDlg.Create(application) do begin
        try
            edittext(debug);
            if ShowModal= 0 
            then debug:= getText;
        finally
            free;
        end;
    end;
end;
end.

1 个答案:

答案 0 :(得分:2)

THTMLEdit.EditText方法中:

...
wbBrowser.Navigate(f);
Doc := GetDocument;
if Doc <> NIL
then Doc.Body.SetAttribute('contentEditable', 'true', 0);  **Crash HERE**
...

wbBrowser.Navigate(f) 异步。当您致电Doc.Body.SetAttribute时,DocDoc.Body 可能尚未准备好/实例化。这是AV的原因。

由于Navigate是异步的,您需要等待TWebBrowser完全加载并初始化其DOM。这通常通过例如:

来完成
  wbBrowser.Navigate(f);
  while wbBrowser.ReadyState <> READYSTATE_COMPLETE do
    Application.ProcessMessages;
  ...

由于Application.ProcessMessages被视为&#34; evil&#34;,并且可能导致重新进入问题(除非您正确处理),更好的方法应该是使用TWebBrowser.OnDocumentComplete事件文档/框架完全加载的地方,并在那里访问(准备/初始化)DOM。