2016-09-20 3 views
0

Я использую uHTMLEdit.pas, предоставленный в RadPHP 3, в виде HTML-редактора (на основе TWebbrowser).
Когда я загружаю некоторые файлы HTML, программа вылетает из строя. В качестве примера сохраните эту страницу StackOverflow и загрузите ее в TWebbrowser. Это приведет к краху:TWebBrowser падает с файлами MOST html

Crash детали:

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. 
+3

AV, вероятно, b/c либо Doc, либо Body не создаются в тот момент, когда вы вызываете 'Doc.Body.SetAttribute'. Я ничего не знаю о uHTMLEdit.pas. Попробуйте загрузить файл непосредственно в 'TWebBrowser', а затем установите его:' Body.SetAttribute ... 'в событии завершения документа. помните, что по умолчанию TWebBrowser использует режим совместимости с IE7. см. http://stackoverflow.com/questions/25843845/how-to-have-delphi-twebbrowser-component-running-in-ie9-mode – kobik

+0

Кроме того, чтобы переключиться в режим редактирования, вы также можете попробовать 'Doc.DesignMode: = 'On'' после того, как документ будет полностью загружен. – kobik

+1

@ kobik-Я не думаю, что это причина. Код работает для некоторых файлов. Итак, Doc создается. – Ampere

ответ

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 либо Doc, либо Doc.Bodyможет еще не подготовлен/создан. это и есть причина АВ.

С Navigate является асинхронным, вам нужно дождаться TWebBrowser, чтобы полностью загрузить и инициализировать его DOM. Это обычно делается, например:

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

Поскольку Application.ProcessMessages считается «злым», и может привести к повторным входным вопросам (если Вы не обрабатывать его правильно), лучший подход должен использовать TWebBrowser.OnDocumentComplete события, где документ/кадр полностью загружен и доступ к (готовому/инициализированному) DOM там.