Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Hello, World!
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  16:20[Войти] | [Зарегистрироваться]

Как запустить Internet Explorer или подключиться к нему.

Сергей Осколков
дата публикации 06-05-2005 07:46

Как запустить Internet Explorer или подключиться к нему

В продолжение нескольких статей на Королевстве о работе с компонентом TWebBrowser хочу затронуть пару вопросов работы с Internet Explorer, которые раньше, кажется, не обсуждались. Почти все уже было в ответах Круглого стола, здесь - более подробно. Сначала немного теории

Internet Explorer и его объекты.

На рисунке изображена архитектура Internet Explorer (IE). Для того, чтобы соединить компоненты в целое, используются элементы  ActiveX  и интерфейсы ActiveDocument. Сам исполняемый файл IE мал (у меня на машине IE6 - 89 КБ). Он предоставляет окно и панель инструментов и непосредственно управляет элементом-браузером WebBrowser (ShDocVw.dll). Этот элемент, в свою очередь, управляет компонентом MSHTML.dll, который осуществляет парсинг (разбор) html и его отображение в окне браузера, а также предоставление документа в виде объектной модели. MSHTML, в свою очередь, управляет скриптовыми движками, плагинами и т.д. для отображения своего содержимого. WebBrowser также управляет активными документами, которые могут быть в него загружены, например документами MS Office. Как WebBrowser,  так и MSHTML предоставляют свои интерфейсы для внешних программ. Первый из них может использоваться как элемент ActiveX. Компонент TWebBrowser из палитры компонентов Дельфи - это просто обертка для него.

Практические выводы из написанного следующие: для управления браузером в целом обычно мы используем методы TWebBrowser. Например, для загрузки документа или его печати. Для доступа к элементам документа мы используем интерфейсы, объявленные в MSHTML, основной из которых - IHtmlDocument2, получаемый через свойство TWebBrowser.Document. Еще я бы отметил интерфейс IHtmlWindow, который соответсвует объекту window в javascript. Через него также можно выполнить ряд полезных действий и получить доступ к элементам страницы. Теперь - к более конкретным вопросам.

Создаем и запускаем.

Напомню, что компонент TWebBrowser и интерфейс IWebBrowser2 - основной интерфейс для управления браузером, объявлены в модуле ShDocVw.pas.  Для работы с интерфейсами MSHTML нужно импортировать одноименную библиотеку типов MSHTML.tlb (меню Project->Import Type Library, выбрать Microsoft Html Object Library).

Первая задача: запустить Internet Explorer и открыть в нем документ. Для запуска можно, конечно, воспользоваться функциями CreateProcess или ShellExecute, как для любой другой программы. Однако мы воспользуемся рассматриваемыми методами.

procedure TMainForm.Open(URL: string);
var WB: IWebBrowser2;
begin
  WB:=CoInternetExplorer.Create;
  WB.Visible:=True;
  WB.Navigate(URL, EmptyParam, EmptyParam, EmptyParam, EmptyParam);
  WB:=nil;
end;

Здесь мы запускаем IE и открываем в нем нужный документ с диска или Веб-страницу.  Если не уничтожать переменную WB сразу же, как в примере, то через нее мы имеем доступ к загруженному документу и также можем управлять экземпляром IE. Например, закрыть его. Непосредственно в интерфейсе IWeBrowser2 метода для этого нет. Однако в ShDocVw.pas объявлен интерфейс IWebBrowserApp = interface(IWebBrowser), который содержит метод Quit.  Я не очень понимаю, почему это так, но работает и (WB as IWebBrowserApp).Quit, и просто WB.Quit - закрывается запущенный экземпляр IE.

В модуле ShDocView также определен тип TInternetExplorer. Им тоже можно пользоваться в описанных целях. 


...
type
  TMainForm = class(TForm)
  ....
    procedure MyBeforeNavigate2(Sender: TObject; var pDisp: OleVariant;
              var URL: OleVariant; var Flags: OleVariant;
              var TargetFrameName: OleVariant; var PostData: OleVariant;
              var Headers: OleVariant; var Cancel: OleVariant);
  public
    IE: TInternetExplorer;
  ....
  end;
...
implementation
...
procedure TMainForm.btnIECreateClick(Sender: TObject);
begin
   if IE=nil then
   begin
     IE:=TInternetExplorer.Create(nil);
     IE.Visible:=True;
     IE.OnBeforeNavigate2:=MyBeforeNavigate2;
     IE.Navigate('d:\Internet\update.htm');
   end;
end;

procedure TMainForm.MyBeforeNavigate2(Sender: TObject; var pDisp, URL,
  Flags, TargetFrameName, PostData, Headers, Cancel: OleVariant);
begin
  Memo.Lines.Add(URL);
end;

procedure TMainForm.btnIECloseClick(Sender: TObject);
begin
  IE.Quit;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  IE.Free;
end;

В примере запускается Internet Explorer, мы подключаемся к его событию OnBeforeNavigate2 и открывается страница (здесь - с жесткого диска). При дальнейших переходах IE на другие страницы, строка адреса (URL) будет добавляться в элемент Memo. Мы также имеем возможность закрыть этот экземпляр IE из своей программы методом IE.Quit.

Подключаемся.

 Следующая задача - подключиться к уже запущенному экземпляру IE. Если попытаться использовать функцию

GetActiveOleObject('InternetExporer.Application');

то мы получим сообщение об ошибке EOleSysError с сообщением "Операция недоступна". Дело в том, что, видимо из соображений безопасности, IE  как сервер автоматизации, после запуска недоступен внешним программам. Это осуществлено так: при старте любой сервер автоматизации регистрирует себя с помощью функции CoRegisterClassObject. Если установить соответствующий флаг (REGCLS_SINGLEUSE) в этой функции, то объект будет недоступен другим приложениям.

Однако, подключиться к интерфейсу IWebBrowser2 запущенного IE все-таки можно! В том же модуле ShDocVw.pas объявлен интерфейс IShellWindows. Через него можно подключиться ко всем открытым окнам IE и Проводника (Explorer)  Windows. Отличить первые от вторых можно по наличию свойства Document. Для доступа воспользуемся стандартными для коллекций  методом Item(i) и свойством Count.

Здесь я натолкнулся на один подводный камень. Попробуем вывести адреса загруженных страниц во всех экземплярах IE в компонент Memo следующим образом:

//ошибочный код
procedure TMainForm.Button2Click(Sender: TObject);
var Winds: IShellWindows;
    i: integer;
begin
  Winds:=CoShellWindows.Create;
  for i:=0 to Winds.Count-1 do
  if (Winds.Item(i) as IWEbBrowser2).Document <> nil //проверка наличия свойства Document
  then Memo.Lines.Add(((Winds.Item(i) as IWEbBrowser2).Document as IHtmlDocument2).url);
end;

При выполнении этот код вызывал ошибку Interface not supported. Оказалось, что у окон проводника свойство Document может быть не равно nil и они благополучно проходят проверку, но при применении оператора as (Document as IHtmlDocument2) возникает исключение, т.к. получить интерфейс IHtmlDocument2 не удается. Как же правильно провести проверку? Здесь можно воспользоваться тем, что в применении к интерфейсам оператор as является оберткой для вызова метода QueryInterface и при компиляции преобразуется в вызовы указанного метода. Метод IUnknown.QueryInterface я и применил. Если окно является окном IE, то мы получим интерфейс IHtmlDocument2, а функция возвратит результат S_OK. В другом случае результат функции будет иным. Работающий код таков:

procedure TMainForm.Button2Click(Sender: TObject);
var Winds: IShellWindows;
    IEWB: IWebBrowser2;
    i: integer;
    Doc: IHtmlDocument2;
begin
  Memo.Clear;
  Winds:=CoShellWindows.Create;
  for i:=0 to Winds.Count-1 do
  if (Winds.Item(i) as IWEbBrowser2).Document&lt;&gt;nil then
  begin
    IEWB:=Winds.Item(i) as IWEbBrowser2;
    if IEWB.Document.QueryInterface(IhtmlDocument2, Doc)= S_OK
    then Memo.Lines.Add(Doc.url);
  end;
end;

Кстати говоря, окна Проводника тоже поддерживают интерфейс IWebBrowser2, и через него можно определить, какая папка открыта в окне в данный момент.

 Подключившись к окну IE мы далее можем управлять им и получить доступ к загруженному  в него документу. Например, можно закрыть все окна, где адрес страницы не отвечает заданным условиям. Можно также получить доступ к событиям IWebBrowser2. Кроме того, в модуле ShDocVw объявлен интерфейс событий DShellWindowsEvents

DShellWindowsEvents = dispinterface
    ['{FE4106E0-399A-11D0-A48C-00A0C90A8F39}']
    procedure WindowRegistered(lCookie: Integer); dispid 200;
    procedure WindowRevoked(lCookie: Integer); dispid 201;
  end;

Если подключиться к нему, то можно отслеживать события возникновения и уничтожения окон IE и Windows Explorer.

Интерфейс IHtmlWindow2

Получив указатель на интерфейс Document: IHtmlDocument2, мы можем через него получить доступ к интерфейсу IHtmlWindow2, который соответствует объекту window в javasript.

var W: IHtmlWindow2;
W:=Document.ParentWindow;

Не буду описывать все его свойства, их можно найти в MSHTML_TLB.pas, упомяну только процедуру

procedure Alert(const message: WideString);

Эта процедура выводит окно с сообщением в браузере. Другой, на мой взгляд, необычный для Дельфи способ использования этого интерфейса - обращение к именованным объектам страницы. Как известно, в javascript объект window является объектом самого высокого уровня в  иерархии, включающим в себя все остальные. К объектам, имеющим имя, можно обращаться через него - window.myObjectName. Если использовать тип OleVariant, т.е. позднее связывание, то это можно использовать и в Дельфи. Пусть на странице есть сценарий javascript, в котором описана функция showsearch(). Открыв эту страницу в TWebBrowser или в IE, как описано раньше, мы можем вызвать эту функцию.

//WB: TWebBrowser

procedure TMainForm.btnDoSearchClick(Sender: TObject);
var W: OleVariant;
begin
  W:=(WB.Document as IHtmlDocument2).parentWindow;
  W.showsearch;
end;






Смотрите также материалы по темам:
[TWebBrowser] [Интеграция с Internet Explorer]

 Обсуждение материала [ 26-06-2020 06:32 ] 27 сообщений
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования