Як запустити Internet Explorer або підключитися до нього, Різне, Програмування, статті

Автор: Сергій Осколков, королівство Delphi

Протягом кількох статей на Королівстві про роботу з компонентом 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:Internetupdate.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<>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;

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*