Re[5]: Internet explorer
От: Ihor Osovyak Украина  
Дата: 07.06.04 08:04
Оценка: 39 (1)
Здравствуйте, Romkin, Вы писали:

R>Здравствуйте, Ihor Osovyak, Вы писали:


А>>>а если мне надо чтоб эксплорер запускался в окне программы?


IO>>Если имеется ввиду полноценный IE — в принцыпе невозможно. Как невозможно в "своем окне" запустить иной процесс.

IO>>Если имеется ввиду активИкс от IE — ради бога — TWebBrowser (D) или как его там в билдере, cppWebBrowser..

>>> А>>>нужно программно запустить IE, передав ему HTML для отображения, который хранится в AnsiString.


IO>>Способов много. Один из вариантов:


R>Да просто http://members.shaw.ca/iedelphi/webbrowser.htm

R>Или просто поискать, уж чего полно, так это решений


Решений то много. Но. См. то же http://members.shaw.ca/iedelphi/webbrowser.htm,
см. ответ на Q: How do I load a string into the WebBrowser without Navigating to a file?

Делаем тестовое приложение. Запускаем в цыкле несколько десятков раз. Теперь берем аналог из моего пред. постинга. Тоже запускаем в цыкле несколько десятков раз. Наблюдаем за количеством занятой памяти. Делаем выводы о наличии утечек памяти в варианте от http://members.shaw.ca/iedelphi/webbrowser.htm и отсутствием такого в моем варианте.

Ключевое различие:
HTMLDocument := WebBrowser1.Document as IHTMLDocument2;
iDoc:= iWB.DefaultInterface.Document as IHtmlDocument2;

Дело здесь в одной довольно малоизвестной ошибке в vcl, связаннной с подсчетом использований интерфейсных ссылок, а именно в TOleControl.GetIDispatchProp. Ошибка присутствует и в пятерке, и в шестерке. За D4, D7 говорить не буду — не смотрел.

При использовании фрагмента вида WebBrowser1.Document происходит вызов TOleControl.GetIDispatchProp,
при работе в стиле WebBrowser1.DefaultInterface.Document — не происходит.

Тема несколько раз обговаривалась в разных форумах.

Суть ошибки — реализация TOleControl.GetIDispatchProp провоцирует компилятор не генерировать один необходимый _Release. Компилятор он правильно работает в данном случае, реализация метода уж очень хитра. Две строчки кода и такая красивая ошибка.



function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;
var
  Temp: TVarData;
begin
  GetProperty(Index, Temp);
  Result := IDispatch(Temp.VDispatch);
end;



Для кода, делающего присваивание интерфейсной ссылки результату компилятор неявно сгенерирует _AddRef. И правильно сделает.
В момент ухода из области видимости Temp неявный вызов _Release генерироваться не будет — что тоже правильно — откуда компилятору знать, что в Temp который TVarData в этот момент живет интерфейсная ссылка? А как результат — имеем один лишний _AddRef. И как следствие — соотв. IHtmlDocument2 будет жить в памяти долго, несмотря на то, что он давным давно выгружен из броузера и никому уже не нужен. Будет жить до последних мгновений жызни программы. Слава богу, что имеем дело с inproc server ..
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.