Рассылка закрыта
При закрытии подписчики были переданы в рассылку "О карьере и профессиональном развитии IT-специалистов" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
← Январь 2004 → | ||||||
1
|
2
|
3
|
4
|
|||
---|---|---|---|---|---|---|
5
|
6
|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
16
|
17
|
18
|
19
|
21
|
22
|
23
|
24
|
25
|
|
26
|
27
|
28
|
29
|
30
|
31
|
Статистика
-4 за неделю
Программирование для начинающих и не только
Информационный Канал Subscribe.Ru |
Плагины для браузеров
Каким бы крутым не был ваш браузер всегда найдется возможность его улучшить и дополнить новыми возможностями. Один из способов это сделать - написать специальный модуль, который будет взаимодействовать с ним дополняя теми или иными возможностями. В этой статье пойдет речь о том как можно создать такой модуль средствами Delphi.
Немного теории
Большинство известных Интернет-медиа форматов таких как Macromedia Shockware, Flash, PDF и т.п. так и остались бы загадкой для браузера, если бы не Netscape, который разработал стандарт для создания плагинов. И который поддерживается большинством браузеров (Opera, Mozilla, Netscape, Konqueror:). Этот стандарт - многоплатформенный. Так сегодня Plugin SDK поддерживает платформы Windows, Unix, и Mac. Естественно такое многообразие платформ поддерживается за счет уже портированных языков программирования коим является C. Что же тогда делать сторонникам Delphi. К счастью народные умельцы часто выставляют на свои (и чужые) сайты портированный под Delphi код для разработок в той или иной области. Это касается и Plugin SDK, Который можно найти на www.torry.net. Англоязычную версию мануала по разработке плагинов можно скачать с сайта Netscape или Mozilla.
После этой подготовки можно заняться разработкой самого плагина.
Постановка задачи

Для начала мы поставим себе за цель написать плагин, который бы отображал в окне браузера форму с кнопкой(рис.1). И разработаем реакцию кнопки на нажатие в которой проведем простые действия над формой.
Реализация
Перейдем собственно к написанию плагина. Для начала откроем Delphi и создадим новое приложение с помощью (DLL Wizard). Далее в теле модуля экспортируем функции:
И не забудем включить в секцию Uses файл под названием npapi.pas в котором содержаться прототипы всех необходимых функций.exports NP_GetEntryPoints index 1 name 'NP_GetEntryPoints', NP_Initialize index 2 name 'NP_Initialize', NP_Shutdown index 3 name 'NP_Shutdown';
Как можно заметить из названия:
- Функция NP_Initialize вызывается при первом обращении к плагину. Она имеет довольно простое определение:
function NP_Initialize(pFuncs:PNPNetscapeFuncs):TNPError;export; stdcall;
параметр pFuncs задает указатель на структуру функций которые должен вызывать плагин для взаимодействия с браузером. Возвращаемое значение (простой int16) показывает результат выполнения работы. - Функция NP_Shutdown - вызывается для завершения работы плагина.
function NP_Shutdown:TNPError;export; stdcall;
- Функция NP_GetEntryPoints - вызывается для передачи браузеру функций управления плагином.
function NP_GetEntryPoints(pFuncs:PNPPluginFuncs):TNPError; export; stdcall;
Как и в NP_Initialize параметр задает указатель на структуру. Но в этот раз она хранит функции которые управляют работой самого плагина.
Теперь давайте поближе рассмотрим структуры NPNetscapeFuncs и NPPluginFuncs:
PNPPluginFuncs = ^TNPPluginFuncs; | |
TNPPluginFuncs = packed record | |
Size : uint16; | Размер структуры |
Version : uint16; | Версия плагина |
newp : TNPP_New; | Вызывается при создании нового экземляра плагина. Может вызыватья, когда в документе отображается больше одного внедренного объекта даного MIME типа, или призапуске 2-х и больше копий браузера, которые отображают одит документ |
destroy : TNPP_Destroy; | Удаления копии плагина. Вызывается когда пользователь покидает страницу с внедренным объектом либо закрывает ее. |
Setwindow : TNPP_SetWindow; | Вызывается для "оконных" плагинов т.е. плагинов, которые отображают информацию в выделенной брузером области |
newstream : TNPP_NewStream; | Создается для записи браузером информаци необходимой для работи плагина |
Destroystream : TNPP_DestroyStream; | Очистка и удаление выделенной NewStream области памяти |
asfile : TNPP_StreamAsFile; | Передача имени файла в котором сохраняется необходимая плигину информация (например PDF формат). |
writeready : TNPP_WriteReady; | Возвращает количество байтов, которые может принять плагин в данным момент |
write : TNPP_Write; | Непосредственная передача информации в плагин |
Print : TNPP_Print; | Запрос на печать информации |
Event : TNPP_HandleEvent; | Передача платформозависимого события |
PNPNetscapeFuncs = ^TNPNetscapeFuncs; | |
TNPNetscapeFuncs = packed record | |
Size : uint16; | Размер структуры |
Version : uint16; | Версия Браузера |
geturl : TNPN_GetURL; | Посылает запрос браузеру на создание Stream-a для заданного URL |
posturl : TNPN_PostURL; | Посылает информацию на заданный URL по методу POST |
Requestread : TNPN_RequestRead; | Запрос части информации из буфера. |
newstream : TNPN_NewStream; | Запрос на создание плагином нового буфера |
write : TNPN_Write; | Передача информации плагину |
Destroystream : TNPN_DestroyStream; | Закрытие буфера обмена |
status : TNPN_Status; | Вывод сообщения в статусную строку браузера |
uagent : TNPN_UserAgent; | Возвращает поле User-Agent |
memalloc : TNPN_MemAlloc; | Выделение блока пимяти в адресном пространстве браузера |
memfree : TNPN_MemFree; | Удаление выделенной области |
memflush : TNPN_MemFlush; | Перераспределение памяти для выделения максимально возможного объема памяти (Только для MacOS) |
Reloadplugins : TNPN_ReloadPlugins; | Запрос на перезапуск всех плагинов |
Если вы скачали одну из адаптаций Plugin SDK для Delphi(к примеру адаптицию A.N. Kashina), то вам незачем беспокоится об управлении всем этим процессом и заучивать названия и параметры всех функций (хотя это было бы очень даже неплохо). Вы можете сразу приступить к разработке логики плагина, а взаимодействие с браузером возьмет на себя npapi.pas. Если же вы хотите все делать сами, то все равно настоятельно советую вам скачать эту адаптацию и заглянуть в ее исходные коды.
А теперь возьмемся за написание логики программы. К счастью для проверки работоспособности нам не надо придумывать еще один велосипед с титановыми колесами мы воспользуемся до боли знакомым "Hello World":procedure TForm1.Button1Click(Sender: TObject); begin Self.Panel1.Caption:='Hello World'; end;

Регистрация и запуск
После того, как мы написали плагин, надо заставить браузер его запустить. Роемся в мануале, и находим, что браузера, которые поддерживают технологию Netscape Plugin ищут и запускают модули из соответствующей директории (Plugins). Поиск этих модулей основывается на анализе MIME типов внедренных объектов и запуск соответствующих модулей. Но на разных платформах определение MIME типов в модулях не совпадают. Так для MacOS надо в ресурсах модуля определить какие MIME типы относятся к нашему плагину. На Unix-системах MIME определяется через вызов экспортируемой функции NPP_GetMIMEDescription, которая возвращает строку с перечнем поддерживаемых форматов. Здесь также может использоваться функция NPP_GetValue. Ну и в Windows используется информация о версии модуля (в Delphi menu: Project->Options->Version Info)
Здесь надо указать опциональные поля:
- MIMEType
- - определяет MIME типы соответствующие данному плагину. Если их несколько сипользуется символ "|". Например "application/plugin-test | application/plugin-demo".
- FileExtents
- - определяет расширение файла. Если их несколько, то также используется символ "|". Пример "tst | dmo".
- FileOpenFileName
- - определяет описание типа файла. Пример "Simple Plugin Module (*.smp)"
К сожалению как я ни пытался заставить плагин работать с такой настройкой параметров, у меня ничего не получилось. Браузер просто на определял его. Пока что единственным решением этой проблемы может быть ручная задача всех необходимых параметров в файле ресурсов и включение его в модуль посредством директивы {$R
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "Simple Example Plugin\0"
VALUE "FileExtents", "smp\0"
VALUE "FileOpenName", "Simple Plugin File (*.smp)\0"
VALUE "FileVersion", "1, 0, 0, 1\0"
VALUE "InternalName", "TESTING\0"
VALUE "LegalCopyright", "Copyright (C) 2003\0"
VALUE "MIMEType", "application/x-test-plugin\0"
VALUE "OriginalFilename", "TestPLN.dll\0"
VALUE "ProductName", "Testing Plugin\0"
VALUE "ProductVersion", "1, 0, 0, 1\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END

После этого запускаем любимый браузер и для проверки правильности наших действий набираем: opera:plugins (для Opera) about:plugins (для NN и Mozilla) . Если все прошло удачно, то в окне браузера появится что-то вроде этого (рис.3), и вы можете смело загружать свой документ с внедренным в него объектом "application/x-text-plugin":
<html>
<head>
<title>Testing</title>
</head>
<body>
<h1>This is the test</h1>
<embed src="test.smp" width=450 height=400></embed>
</body>
</html>
Усложняем пример
Допустим нам надо отобразить содержимое нашего smp-файла на форме. Но для этого нам сначала надо его прочитать. Для этого воспользуемся компонентом из модуля npapi.pas под названием TNetscapeStream . Запишем объявление этого компонента в секции private нашей формы и в событии OnFormCreate инициализируем ее:
procedure TForm1.FormCreate(Sender: TObject);
begin
NS:=TNetscapeStream.Create(Self);
NS.StreamType:=stAsFile;
NS.OnAsFile:=DoStreamAsFile;
end;
Само определение события OnAsFile выглядит следующим образом:
TAsFileNotify = procedure (Sender:TObject; FileName:PChar) of object;
Где
Теперь в обработчике жтого события мы просто читаем содержимое файла
procedure TForm1.DoStreamAsFile(Sender:TObject;FileName:PChar);
var FS:TFileStream;
S:String;
begin
FS:=TFilestream.Create(FileName,fmOpenRead);
try
SetLength(S,1024);
FS.ReadBuffer(Pointer(S)^,Min(FS.Size,1024));
Panel1.Caption:=S;
finally
FS.Free;
end;
end;
Кроме этого для разрешения приема данного файла нам необходимо вызвать метод Accept класса TNetscapeStream. Вызвать его надо в обработчике сообщения NM_NewStream, которое определено в файле npapi.pas и которое вызывается во время запроса на создание нового экземпляра TNetscapeStream с параметрами wParam=0 и lParam - указатель на структуру PNPStream. Код реализации этого метода приведен ниже:
procedure TForm1.DoNewStream(var Message:TMessage);
begin
NS.Accept(PNPStream(Message.LParam),InstanceID);
inherited;
end;

После этого перезапускаем браузер и видим рис.4 то, что и должны были увидеть.
Последние штрихи
Теперь уже мы знаем, как писать плагины для Интернет браузеров. Самое время подумать над тем, а для чего это можно использовать т.е. что реально может делать наш плагин кроме как выводить формы с кнопочками. Можно например разработать какой-нибудь формат хранения графики, видео или аудио информации, а затем при помощи плагинов отображать ее. Можно сделать плагин, который будет к примеру вести учет посещаемых ссылок (например MSIE Spy из состава ReGet рис.5), или же разработать свой менеджер закачки и при помощи плагинов интегрировать его в Браузер. Но эту задачу конечно же придется решать вам.

*
Конечно же разработка плагинов не панацея от ограниченной функциональности браузера. Она позволяет решать только достаточно узкий круг задач по отображению контента HTML страниц. А точнее отображение только данных заданных тэгом <EMBED> или зарегистрированных при помощи MIME типов. Тем не менее основным ее достоинством есть открытость и доступность для разных платформ (как уже говорилось Windows, Mac, Unix). Но сегодня функциональных возможностей предоставляемых Plugin SDK явно недостаточно, а потому многие браузеры (Opera и конечно же Internet Explorer) начали поддерживать дополнительные расширения на основе ActiveX. Так к примеру тот же MSIE Spy от Reget реализован на основе ActiveX. Так же реализованы OperaClickCatcher т.е. плагин для Opera призванный по щелчку мыши скачивать заданный линк или перехватывать начало закачки передавая ее в Reget.
P.S. В листингах приведены исходные коды нашей формы и библиотеки.
//Листинг.1 Код библиотеки
library MyPlugin;
uses
SysUtils,Classes,npapi,Unit1 in 'Unit1.pas' {Form1};
{$R Test.res}
exports
NP_GetEntryPoints index 1 name 'NP_GetEntryPoints',
NP_Initialize index 2 name 'NP_Initialize',
NP_Shutdown index 3 name 'NP_Shutdown';
begin
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,npapi, StdCtrls, ExtCtrls;
type
TForm1 = class(TPluginForm)
Button1: TButton;
Panel1: TPanel;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
NS:TNetscapeStream;
procedure DoStreamAsFile(Sender:TObject;FileName:PChar);
procedure DoNewStream(var Message:TMessage);message NM_NewStream;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
Uses Math;
{$R *.dfm}
procedure TForm1.DoNewStream(var Message:TMessage);
begin
NS.Accept(PNPStream(Message.LParam),InstanceID);
inherited;
end;
procedure TForm1.DoStreamAsFile(Sender:TObject;FileName:PChar);
var FS:TFileStream;
S:String;
begin
FS:=TFilestream.Create(FileName,fmOpenRead);
try
SetLength(S,1024);
FS.ReadBuffer(Pointer(S)^,Min(FS.Size,1024));
Panel1.Caption:=S;
finally
FS.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
NS:=TNetscapeStream.Create(Self);
NS.StreamType:=stAsFile;
NS.OnAsFile:=DoStreamAsFile;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
NS.Free;
end;
initialization
RegisterPluginForm(TForm1);
end.
http://subscribe.ru/
E-mail: ask@subscribe.ru |
Отписаться
Убрать рекламу |
В избранное | ||