Здесь мы запускаем IE и открываем в нем нужный документ с диска или Веб-страницу. Если не уничтожать переменную WB сразу же, как в примере, то через нее мы имеем доступ к загруженному документу и также можем управлять экземпляром IE. Например, закрыть его. Непосредственно в интерфейсе IWeBrowser2 метода для этого нет. Однако в ShDocVw.pas объявлен интерфейс IWebBrowserApp = interface(IWebBrowser), который содержит метод Quit. Я не очень понимаю, почему это так, но работает и (WB as IWebBrowserApp).Quit, и просто WB.Quit - закрывается запущенный экземпляр IE. В модуле ShDocView также определен тип TInternetExplorer. Им тоже можно пользоваться в описанных целях.
В примере запускается 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 следующим образом:
При выполнении этот код вызывал ошибку Interface not supported. Оказалось, что у окон проводника свойство Document может быть не равно nil и они благополучно проходят проверку, но при применении оператора as (Document as IHtmlDocument2) возникает исключение, т.к. получить интерфейс IHtmlDocument2 не удается. Как же правильно провести проверку? Здесь можно воспользоваться тем, что в применении к интерфейсам оператор as является оберткой для вызова метода QueryInterface и при компиляции преобразуется в вызовы указанного метода. Метод IUnknown.QueryInterface я и применил. Если окно является окном IE, то мы получим интерфейс IHtmlDocument2, а функция возвратит результат S_OK. В другом случае результат функции будет иным. Работающий код таков:
Кстати говоря, окна Проводника тоже поддерживают интерфейс 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, как описано раньше, мы можем вызвать эту функцию.
Автор: Сергей Осколков
|