Учебная работа. Статья: Связка ActiveX — Internet Explorer
Иван Семенов
А понимаете ли вы, что на Delphi можно писать activeX составляющие? Естественно понимаете. А что с помощью их можно вести взаимодействие с Internet Explorer? Это быть может любопытно для проф веб-мастеров, скажете вы, но я не согласен. «Обычной» программер тоже может отыскать массу применений этому. тут будет описано одно из их. Все мы лазим (ходим и т.д.) по Вебу. И вы тоже — раз читаете эти строчки :). А не бывало ли для вас, случаем кое-где побывав, что-то прочитав и благополучно забыв адресок веб-сайта через некое время вдруг осознать, что там было конкретно то, что для вас на данный момент срочно пригодилось? Можно естественно поглядеть History браузера, можно залезть в кэш «руками» и попробовать отыскать там что-то. А можно написать компонент, который бы находил слова в файлах кэша (в общем случае в всех html-файлах) и выводил бы на просмотр требуемые файлы. Связать этот компонент с Эксплорером — и вперед. Что комфортно — вся работа происходит в эксплорере: и поиск, и,естественно, просмотр. При всем этом для Delphi-программиста не необходимы особенные познания языка html, скриптовых языков и т.п. Довольно знать несколько главных конструкций (а уж справочных руководств в Вебе весьма много). Написанный ActiveX-компонент вставляется в html-страничку. Вот вам наглядный пример простейшей страницы
<html>
<HEAD>
<TITLE>Поиск</TITLE>
</HEAD>
<BODY>
<P ALIGN=CENTER>
<OBJECT ID=»findword1″ — {с помощью этого тэга компонент вставляется в страницу}
CLASSID=»CLSID:47E50425-E611-11D3-970A-4854E82B17E6″
CODEBASE=»C:PathFINDWORDS.OCX»>
</OBJECT>
</P>
</BODY>
</HTML>
В этом примере activeX-компонент, находящийся в файле C:PATHFINDWORDS.OCX вставляется в html-страничку. Но принципиально отметить, что эта страница раскроется лишь в Microsoft Internet Explorer версии 4 и старше. Пишут, что 3-ий эксплорер тоже поддерживает тэг <OBJECT>, но сам не пробовал, не понимаю. Браузеры Netscape, Opera и какие еще там бывают, его не поддерживают.
Итак, тэг <OBJECT> вставляет в страницу activeX-компонент. Его атрибут CLASSID показывает идентификатор класса нашего компонента. При разработке в Delphi компонента с нуля ему автоматом присваивается этот идентификатор класса. ID=»findword1″ — имя объекта. Тут можно писать хоть какое имя. По нему мы в предстоящем будем ссылаться на наш компонент в теле страницы из скриптов-процедур обработки событий. Дальше, для того, чтоб наш компонент мог употребляться прикладными программками, он должен быть зарегистрирован в реестре. Зарегистрировать его можно программкой regsvr32, которая по дефлоту находится в каталоге [System]. к примеру так: [regsvr32 C:PATHFINDWORDS.OCX]. Если при открытии страницы Explorer не находит в реестре обозначенный компонент, то он отыскивает его в местоположении, обозначенном атрибутом CODEBASE. тут быть может полный путь к файлу, если он находится на вашем твердом диске либо даже URL-адресок (со всеми сопутствующими атрибутами, как то HTTP:// и т.д.).Т.е, если эксплорер повстречал ссылку на компонент, а этого компонента нету на вашей машине, он может загрузить его из веба с обозначенного адреса. К слову, атрибут CLASSID — неотклонимый, конкретно по нему делается «идентификация» класса. А атрибут CODEBASE — необязательный. В случае, когда он опущен, если компонент уже зарегистрирован в системе, то он отобразится в вашей странице, если не зарегистрирован — страница будет пустой. И в конце концов если эксплорер сам регистрирует компонент, он переписывает файл OCX в папку [WindowsDownloaded program files].
Для того, чтоб вручную не писать скрипты подсоединения activeX компонент, я советую скачать программку Microsoft activeX Control Pad отсюда. Эта программка создана для внедрения activeX-компонентов в HTML-странички. Опосля ее работы определение компонента смотрится приблизительно так:
<OBJECT ID=»findword1″
CLASSID=»CLSID:47E50425-E611-11D3-970A-4854E82B17E6″
CODEBASE=»C:PathFINDWORDS.OCX»>
<PARAM NAME=»Visible» VALUE=»-1″>
<PARAM NAME=»AutoScroll» VALUE=»0″>
<PARAM NAME=»AutoSize» VALUE=»0″>
<PARAM NAME=»AxBorderStyle» VALUE=»1″>
<PARAM NAME=»Caption» VALUE=»findword»>
<PARAM NAME=»Color» VALUE=»2147483663″>
<PARAM NAME=»Font» VALUE=»MS Sans Serif»>
<PARAM NAME=»KeyPreview» VALUE=»0″>
<PARAM NAME=»PixelsPerInch» VALUE=»96″>
<PARAM NAME=»PrintScale» VALUE=»1″>
<PARAM NAME=»Scaled» VALUE=»-1″>
<PARAM NAME=»DropTarget» VALUE=»0″>
<PARAM NAME=»HelpFile» VALUE=»»>
<PARAM NAME=»DoubleBuffered» VALUE=»0″>
<PARAM NAME=»Enabled» VALUE=»-1″>
<PARAM NAME=»BiDiMode» VALUE=»0″>
<PARAM NAME=»Cursor» VALUE=»0″>
<PARAM NAME=»filename» VALUE=»nothing»>
</OBJECT>
Т.е. эта программка сама подставляет полное определение компонента (его CLASSID, к примеру). правда, приобретенный код время от времени приходится подправлять вручную. к примеру может потребоваться убрать очевидное указание высоты и ширины объекта.
сейчас подходим к самому основному: как создать сам компонент (чтоб было что вставлять в нашу страницу :). Итак, в Delphi делаем NewactiveXActive form. В окошке Active Form Wizard избираем Threading model=Apartment. Остальные threading models не работают с IE 4. Смотрится это так: компонент в странице раскрывается, но время от времени вдруг выскакивает Access violation. (обычно на событие Create). Модель же Both работает с IE 5. Флаг «Include Design-Time licence» лучше не устанавливать. Далее раскрывается новенькая форма, где вы сможете располагать свои кнопки-текстбоксы, определять реакцию на действия и т.д.
Дальше будут описаны некие хитрости. к примеру, необходимо хранить некие данные во наружном файле. Я столкнулся со последующим: мой компонент на различных машинках располагал свои файлы в различных местах: на одной в каталоге Windows, на иной — на десктопе. Был найден таковой выход: пусть страница по просьбе компонента возвращает ему каталог, в каком она находится. Для этого на форму я расположил PageControl, сделал закладки невидимыми и на OnShow (у формы activeX компонента нет действия OnShow) одной из страничек поставил генерацию собственного действия OnWantDir. А в теле HTML-странички соответственно реакцию на него:
<Script LANGUAGE=»VBScript»>
<!—
Sub findword1_OnWantDir()
findword1.Page_location = location.href
end sub
—>
</SCRIPT>
Дальше, это событие OnShow происходит сходу опосля сотворения экземпляра компонента. Итак вот, если событие OnWantDir генерировать конкретно в нем (в OnShow), то видимо что-то в недрах Windows не успевает провернуться и машинка виснет. Потому пришлось повесить на форму таймер, на OnShow таймер запускать, и уже на OnTimer как раз и вызывать свое событие OnWantDir. Интервал у таймера я поставил в полсекунды. естественно можно было бы хранить свои файлы к примеру в каталоге [Windows], но почему-либо функция GetWindowsDirectory при вызове из activeX-компонента возвращала ошибку, хотя здесь же нормально отрабатывала из обычного приложения (exe). То же и с GetSystemDirectory и GetTempDirectory.
Как создать компонент тиражируемым? Чтоб юзер сумел работать с ним сходу же, не запуская никаких доп программ, не указывая всяких-разных путей и т.д. Вот вам наглядный пример html-странички (а тут его снимок экрана):
<html>
<HEAD>
<title>Поиск</title>
<Script LANGUAGE=»VBScript«>
<!—
Sub Procedure1()
location.href = findword1.NewStroke
{Получить от компонента имя файла и открыть его для просмотра. Эта процедура запускается при появлении действия OnDocClick. Location — объект Explorer’а (см. документацию по VBScript)}
end sub
—>
</Script>
</HEAD>
<SCRIPT LANGUAGE=»VBScript»>
<!—
Sub findword1_OnWantDir()
findword1.Page_location = location.href
{Получить текущий каталог, т.е. свойству page_location объекта присвоить положение нашей страницы}
end sub
Sub findword1_OnDocClick()
{При появлении действия OnDocClick вызвать функцию Procedure1 (открыть файл для просмотра)}
call Procedure1()
end sub
—>
</SCRIPT>
<p align = «center»>
<OBJECT ID=»findword1″
CLASSID=»CLSID:47E50425-E611-11D3-970A-4854E82B17E6″
CODEBASE=»findwords.ocx»>
{Тут просто имя файла без пути. Explorer зарегистрирует компонент невидимо для юзера, взяв его из текущеего каталога (страница и файл OCX находятся в одном каталоге)}
<PARAM NAME=»Visible» VALUE=»-1″>
<PARAM NAME=»AutoScroll» VALUE=»0″>
<PARAM NAME=»AutoSize» VALUE=»0″>
<PARAM NAME=»AxBorderStyle» VALUE=»1″>
<PARAM NAME=»Caption» VALUE=»findword»>
<PARAM NAME=»Color» VALUE=»2147483663″>
<PARAM NAME=»Font» VALUE=»MS Sans Serif»>
<PARAM NAME=»KeyPreview» VALUE=»0″>
<PARAM NAME=»PixelsPerInch» VALUE=»96″>
<PARAM NAME=»PrintScale» VALUE=»1″>
<PARAM NAME=»Scaled» VALUE=»-1″>
<PARAM NAME=»DropTarget» VALUE=»0″>
<PARAM NAME=»DoubleBuffered» VALUE=»0″>
<PARAM NAME=»Enabled» VALUE=»-1″>
<PARAM NAME=»BiDiMode» VALUE=»0″>
<PARAM NAME=»Cursor» VALUE=»0″>
<PARAM NAME=»filename» VALUE=»nothing»>
<PARAM NAME=»Page_location» VALUE=»»>
</OBJECT>
</p>
</BODY>
</html>
И снова: 1) открываем нашу страницу (в IE 4 и выше); 2) если компонент зарегистрирован, он сходу показывается, если не зарегистрирован, то регится и показывается. При всем этом: 3) опосля сотворения выдерживается пауза в полсекунды и запрашивается текущий каталог (и страница и сам OCX-файл находятся в одном каталоге, который и будет текущим). 4) если необходимо открыть на просмотр какую или страницу (избранную юзером в процессе работы из перечня — см. снимок экрана), то свойству компонента (при внедрении его в страницу вернее будет именовать его уже объектом) присваивается файл.
]]>