Технологии ActiveX в языке Object RSL - R

advertisement
<Секреты языка RSL>
Технологии ActiveX в языке Object RSL
Продолжая тему, начатую в статье В.Волошина «Современные технологии Microsoft —
стратегическое направление развития Object RSL и Visual RSL» (см. «RS-Club», 1998, №
3/10/, с.78—80), автор настоящей публикации рассказывает о новшествах, появившихся в
языке Object RSL для поддержки технологий ActiveX.
Сергей Кубрин
ведущий специалист Отдела исследований
компании «R-Style Software Lab.»
Создание ActiveX объектов
Как мы уже информировали наших читателей (см. статью С.Кубрина «Новые
возможности макроязыка RSL» — «RS-Club», 1998, № 3/10/, с.78—80), сегодня пользователи
Object RSL могут создавать ActiveX-объекты (объекты автоматизации) и обращаться к их
свойствам и методам из RSL-программы. Делается это очень просто — нужно лишь
импортировать модуль rslx и вызвать стандартную процедуру ActiveX. Ее первым
параметром является идентификатор объекта, вторым (он необязателен) — имя компьютера,
на котором создается объект. В новой версии интерпретатора процедура может иметь и
третий, дополнительный параметр. Если он равен «true», то ActiveX пытается вернуть
ссылку на уже существующий объект, а не создавать его новый экземпляр. Вот небольшой
пример:
import rslx;
ob = ActiveX ("Excel.Application",null,true);
ob.Visible = true;
ob.Workbooks.add;
ob.Workbooks.add;
ob.Workbooks.add;
MsgBox ("Нажмите любую клавишу для выхода их Excel");
1
ob.Quit;
В приведенном фрагменте программы мы сначала подключились к объекту
автоматизации Excel.Application. (Если приложение Excel уже было запущено, то его новая
копия благодаря третьему параметру функции ActiveX не запускается.) Затем, используя
Excel.Application, добавили три рабочие книги Excel. Как видно из примера, способ
обращения к свойствам и методам объекта автоматизации ничем не отличается от обращения
к свойствам и методам объекта RSL.
Поддержка стандартных коллекций
Приложения типа Excel экспортируют большое количество полезных объектов
автоматизации. Многие из этих объектов являются контейнерными, представляя собой
коллекции других объектов. Для создания таких коллекций и доступа к их содержимому
существует
специальный
стандарт,
в
значительной
степени
облегчающий
жизнь
пользователям подобных приложений.
Так, например, в редакторе Excel есть коллекция рабочих книг. Пусть переменная ob
содержит ссылку на объект Excel.Application. Используя средства Visual Basic, можно
перебрать все рабочие книги коллекции:
For Each p In ob.Workbooks
MsgBox p.Name
Next p
Object RSL тоже теперь позволяет использовать стандартные коллекции. При этом,
чтобы реализовать перечисление объектов, для коллекции при помощи предопределенного
метода CreateEnum, который автоматически добавляется к каждому ActiveX-объекту, можно
создать специальный объект-перечислитель. Переведем рассматриваемый код на язык Object
RSL:
En = ob.Workbooks;
While (En.Next )
MsgBox (En.Item.Name)
End;
2
В этой программе для навигации по коллекции используется метод Next объектаперечислителя. Когда коллекция просмотрена до конца, данный метод возвращает значение
«false». Ссылка на очередной элемент хранится в свойстве Item. Еще один метод объектаперечислителя — Reset. После его вызова можно всю итерацию повторить снова.
В будущем Object RSL пополнится специальным объектом для создания коллекций, а
пока в качестве стандартной коллекции может выступать объект Tarray:
Ar = Tarray;
Ar (0) = "Element 1";
Ar (1) = "Elemrnt 2";
En = Ar.createEnum;
While (En.next)
Println (En.Item)
End;
Свойства объектов с параметрами
Кроме обычных свойств, объекты автоматизации могут содержать свойства с
параметрами, к которым теперь можно обращаться из Object RSL. Рассмотрим пример:
ob = ActiveX ("XArray.XArray");
ob.ReDim (0,10,0,20); /* У массива будет две размерности 0-10 и 0- 20 */
i = 0;
while (i < 10)
ob.Value (i,0) = "String "+i;
i=i+1
end;
Объект XArray.Xarray реализует двумерный массив. Элементы этого массива хранятся
в свойстве Value, а индексы элементов определяются параметрами данного свойства.
Здесь уместно отметить, что при поддержке свойств с параметрами может
потребоваться внести изменения в существующие программы. Предположим, что есть класс
Object RSL — MyClass:
3
Class MyClass
Var prop = Tarray;
End;
Ob = MyClass;
Раньше присвоить значения элементам массива можно было следующим образом:
Ob.prop (0) = "Строка1";
Ob.prop (1) = "Строка2";
Теперь же в такой записи значения «0» и «1» будут истолкованы как параметры
свойства prop, и после выполнения приведенных инструкций это свойство будет содержать
не массив из двух элементов, а значение «Строка2». Для того чтобы все-таки присвоить
значения элементам массива, следует сделать следующую запись:
Ob.prop ( )(0) = "Строка1";
Ob.prop ( )(1) = "Строка2";
Используя свойство Value, с помощью которого можно обращаться к элементам
массива, приведенные выше инструкции можно переписать иначе:
Ob.prop.Value (0) = "Строка";
Ob.prop.Value (1) = "Строка2";
Доступ к объектам Object RSL из других языков
Пожалуй, наиболее интересная особенность последней версии Object RSL связана с
тем, что все объекты классов этого языка являются объектами автоматизации и,
следовательно, могут быть доступны из других языков программирования. Давайте
рассмотрим пример обращения к объекту Object RSL из Visual BASIC.
Объект Object RSL может быть передан в процедуру Visual BASIC, например, в
качестве параметра. Предположим, что на языке Visual BASIC реализован простой сервер
автоматизации,
к
которому
можно
обратиться,
указав
его
идентификатор
—
VbServer.VbClass. Пусть этот сервер экспортирует следующую процедуру:
4
Public Sub TetRSL (ob As Object)
ob.Test "From Basic", " Parm1 ", "Parm2"
End Sub
Теперь на языке Object RSL создадим два объекта: один — класса RSL, другой —
класса Visual BASIC. Заставим Visual BASIC вызвать метод Test класса Object RSL.
import rslx;
class TestRSLClass
macro Test (p1,p2,p3)
MsgBox ("Вызван метод Test с параметрами: ", p1, " ", p2, " ", p3)
end;
end;
vb = ActiveX ("VbServer.VbClass");
rsl = TestRSLClass;
vb.TestRSL (rsl);
Вот и все. Visual BASIC и «не подозревает», что работает с объектом Object RSL!
Обработка событий на Object RSL
Объекты Object RSL, как и объекты автоматизации, могут иметь не только свойства и
методы, но и события. Дадим определение последнему термину. Итак, событие — это способ
уведомления клиента объекта о происходящих в объекте изменениях. Новая версия Object
RSL позволяет обрабатывать события, то есть принимать сообщения от объектов
автоматизации и выполнять необходимые действия.
Вот, скажем, Excel.Application — объект из нашего первого примера — посылает
уведомление о создании новой рабочей книги. Как возможно организовать обработку такого
сообщения? Очень просто. Нужно создать специальный объект — обработчик событий,
5
который должен принадлежать классу-наследнику стандартного класса TRslEvHandler. Затем
созданному объекту-обработчику необходимо указать, события какого объекта следует
обрабатывать. Запишем все это на языке Object RSL:
import rslx;
class (TrslEvHandler) MyHandler (EvObj)
EvSource ("Excel","Application") = EvObj;
Macro Excel_NewWorkBook (wb)
MsgBox ("Добавлена книга: ", wb.Name)
End
End;
ob = ActiveX ("Excel.Application",null,true);
ob.Visible = true;
Ev = MyHandler (ob);
MsgBox ("Нажмите клавишу для окончания")
Обратите внимание на то, как осуществляется связь объекта-источника (объект ob) с
объектом-обработчиком событий (объект Ev). Стандартный класс TRslEvHandler имеет для
этой цели специальное свойство EvSource, которому для организации обработки сообщений
необходимо присвоить ссылку на объект-источник. В примере это делается посредством
передачи объекта-источника в качестве параметра конструктору класса MyHandler.
Собственно связь налаживается при выполнении инструкции:
EvSource ("Excel","Application") = EvObj;
Первым параметром свойства EvSource является строка, представляющая собой
префикс, который добавляется к именам событий. Таким образом для события
NewWorkBook сформируется имя Excel_NewWorkBook. Когда событие NewWorkBook
произойдет, для его обработки будет вызван метод класса MyHandler с именем
Excel_NewWorkBook.
6
Вообще, свойство EvSource представляет собой массив, который индексируется данной
строкой-префиксом. Подобная организация EvSource позволяет одному объекту-обработчику
событий реагировать на уведомления от разных объектов-источников, даже если у
последних совпадают имена событий. Например, у нас есть два разных объекта
Excel.Application. В приведенной ниже программе реализована обработка сообщений от них
обоих:
import rslx;
class (TrslEvHandler) MyHandler
Macro Excel1_NewWorkBook (wb)
MsgBox ("(1) Добавлена книга: ", wb.Name)
End
Macro Excel2_NewWorkBook (wb)
MsgBox ("(2) Добавлена книга: ", wb.Name)
End
end;
Ev = MyHandler;
Ob1 = ActiveX ("Excel.Application");
Ob1.Visible = true;
Ob2 = ActiveX ("Excel.Application");
Ob2.Visible = true;
Ev.EvSource ("Excel1") = Ob1;
Ev.EvSource ("Excel2") = Ob2;
MsgBox ("Нажмите клавишу для окончания")
Следует заметить, что обращаться к свойству EvSource можно не только в коде
конструктора класса, но и там, где допустимо обращение к любым свойствам и методам.
Второй параметр свойства EvSource задает то имя класса объекта-источника, которое
указано библиотеке типов. В предыдущем примере имя класса — «Application».
7
Большинство объектов автоматизации имеют специальные библиотеки типов, в
которых описываются имена методов, свойств, событий, количество и типы параметров и
многое другое. Информацию из таких библиотек интерпретатор Object RSL использует для
того, чтобы устанавливать соответствие между событиями и методами обработки. В
некоторых случаях Object RSL не способен автоматически найти нужную библиотеку типов,
поэтому существует возможность явно указать, какую библиотеку следует использовать. Для
этого строку с именем библиотеки типов надо присвоить специальному свойству TypeLib
стандартного класса TRslEvHandler. Выполнить такое присвоение необходимо перед
обращением к свойству EvSource. Скажем, в приведенном выше примере с Excel можно
было написать так:
TypeLib = "c:\\Program Files\\Microsoft Office\\Office\\excel8.olb";
EvSource ("Excel","Application") = EvObj;
Object RSL будет использовать информацию из библиотеки типов excel8.olb, не
пытаясь найти ее самостоятельно.
Второй параметр свойства EvSource указывать не всегда обязательно — как правило,
Object RSL автоматически определяет нужное имя класса, но для этого необходимо, чтобы
объект-источник событий являлся объектом Object RSL либо поддерживал специальный
COM интерфейс — IprivideClassInfo. К сожалению, объекты Excel этот интерфейс не
поддерживают, поэтому нам пришлось указывать имя класса явно. Если же предположить,
что IprivideClassInfo поддерживается в Excel, то запись будет выглядеть проще:
EvSource ("Excel") = EvObj;
Чтобы прекратить обработку событий, свойству EvSource нужно присвоить значение
«null», указав в качестве первого параметра соответствующую строку-префикс. Так,
например, если нас больше не интересуют события объекта Ob2, то в код следует добавить
следующую инструкцию:
Ev.EvSource ("Excel2") = null;
Если нас не интересуют все события, которые обрабатываются объектом Ev, то можно
просто удалить объект Ev. Для этого надо присвоить «null» переменной Ev:
8
Ev = null;
Источниками событий могут быть не только внешние объекты автоматизации, но и
объекты Object RSL. Нужно лишь создать класс Object RSL — наследник того же самого
стандартного класса TRslEvHandler. Тогда, чтобы событие произошло, надо будет только
вызвать метод класса TrslEvHandler — raise, который в качестве первого параметра
принимает имя события. Остальные параметры передаются как есть в процедуру обработки
события. Приведем пример класса, который порождает событие onEvent1 при вызове метода
Test:
import rslx;
class (TRslEvHandler) Source
macro Test
raise ("onEvent1", "Это параметр события");
end;
end;
Объект-обработчик выглядит так же, как в примере с Excel:
class (TRslEvHandler) Handler ( ob )
EvSource ("OB") = ob;
macro OB_onEvent1 ( par )
MsgBox ("Событие OnEvent1 с параметром: ", par)
end;
end;
ob = Source;
ev = Handler (ob);
ob.Test
9
Для обработки событий можно также непосредственно создавать экземпляр класса
TrslEvHandler:
import rslx;
Ev = TRslEvHandler;
Ev.EvSource ("OB") = ob;
macro OB_onEvent1 ( par )
MsgBox ("Событие OnEvent1 с параметром: ", par)
end;
В таких случаях объектом-обработчиком является вся RSL-программа. Процедуры
обработки событий должны быть написаны вне любого класса, на уровне модуля Object RSL.
Возможен еще один способ реализации обработки событий — создать объект класса
TrslEvHandler непосредственно, передав конструктору в качестве параметра ссылку на
объект-обработчик событий:
import rslx;
class EvHandler
macro OB_onEvent1 ( par )
MsgBox ("Событие OnEvent1 с параметром: ", par)
end;
end;
Ev = TRslEvHandler (EvHandler);
Ev.EvSource ("OB") = ob;
Для удобства обработки событий Object RSL автоматически создает экземпляр класса
TRslEvHandler. На этот экземпляр ссылается глобальная переменная RslEvHandler. Можно
считать, что Object RSL неявно выполняет следующую инструкцию:
RslEvHandler = TRslEvHandler;
10
Используя глобальную переменную RslEvHandler, программу обработки событий Excel
можно записать проще:
import rslx;
ob = ActiveX ("Excel.Application",null,true);
ob.Visible = true;
RslEvHandler.EvSource ("Excel","Application") = ob;
Macro Excel_NewWorkBook (wb)
MsgBox ("Добавлена книга: ", wb.Name)
End
MsgBox ("Нажмите клавишу для окончания")
И чтобы закончить тему обработки событий, рассмотрим пример использования Object
RSL в качестве скрипта на HTML-странице:
<HTML>
<BODY>
<P> Демонстрация обработки сообщения onClick </P>
<BUTTON ID="CmdButton" STYLE="margin:20%;padding:40">
Press Me
</BUTTON>
<SCRIPT LANGUAGE="RSLScript">
macro CmdButton_onClick
MsgBox ("Нажата кнопка ",event.srcElement.id );
end;
RSLEvHandler.EvSource ("CmdButton") = CmdButton;
</SCRIPT>
</BODY>
11
</HTML>
Здесь обрабатывается событие onClick, закрепленное за кнопкой, которая размещена на
HTML-странице. Как и в случае с Excel, для связи источника с обработчиком событий мы
использовали глобальную переменную RslEvHandler.
О передаче параметров
Стоит уделить некоторое внимание и механизму передачи параметров. Как известно, в
Object RSL параметры передаются процедурам по значению. Тем не менее, вызванная
процедура может изменить значение фактического параметра в процедуре, ее вызвавшей, —
это делается при помощи стандартной процедуры SetParm. Что же касается методов
объектов автоматизации, то они могут принимать параметры по ссылке. Проиллюстрируем
сказанное.
Вот процедура на языке Visual Basic:
Sub BasicProc (ByRef par1 As String, ByRef par2 AS Variant)
Par1 = "New string";
Par2 = 10;
End sub
При вызове данного метода необходимо заставить интерпретатор RSL передать
параметры по ссылке. Для этого используется специальный модификатор :i. Код на Object
RSL будет выглядеть так:
Val1 = "Old string 1";
Val2 = "Old string 2";
Ob.BasicProc ( Val:i, Val2:iv)
Переменная Val1 здесь передается как ссылка на строку. В то же время некоторые
методы объектов автоматизации принимают параметры как ссылки на вариант (в данном
случае таким является параметр par2), благодаря чему эти методы могут менять не только
значение параметра, но и его тип. Для передачи параметров из Object RSL как ссылок на
вариант используется модификатор :iv.
Выше говорилось о том, что в Object RSL параметры передаются по значению. Однако
обработчикам событий, написанных на Object RSL, параметры могут быть переданы по
12
ссылке. В этом случае внутри RSL-кода значение переданного параметра можно изменить
при помощи уже известной процедуры SetParm.
Теперь о передаче методам объектов автоматизации в качестве параметров объектов
типа Tarray. По умолчанию последние передаются, как и любые другие объекты классов
Object RSL. Так, в программе на языке Visual Basic массив Tarray будет выглядеть как
объект, у которого есть свойства size и value. Однако стандарт автоматизации
предусматривает для массивов свой тип данных — SAFEARRAY. Поэтому при
необходимости можно сделать так, чтобы при передаче из Object RSL объекта типа Tarray
этот объект автоматически конвертировался в тип данных SAFEARRAY. Для этого нужно
будет присвоить значение «true» свойству CvtТoСafeАrray объекта Tarray. Вот пример:
Ar = Tarray;
Ar.value (0) = "value for array";
Ar. CvtToSafeArray = true;
При передаче в качестве параметра методам объектов автоматизации массив Ar будет
автоматически преобразовываться в тип SAFEARRAY.
Автоматическое создание объектов Object RSL
Еще одно полезное новшество в Object RSL — автоматическое создание объектов
классов при первом обращении к декларированной переменной типа класса Object RSL:
Class TestClass
Var prop = 10;
End;
Var Ob:TestClass; /* Декларируем переменную типа TestClass */
Println (Ob.prop); /* Объект автоматически создается */
Новый способ обработки ошибок времени выполнения
И последнее, что необходимо отметить, — новый способ обработки ошибок. Теперь
можно осуществить «перехват» любой ошибки времени выполнения, не допустив
13
аварийного завершения RSL-программы. Для этого в новом релизе Object RSL
макропроцедуры и методы класса могут применять обработчики ошибок. Записывается это
следующим образом:
Macro Test
<инструкции RSL>
OnError
<инструкции для обработки ошибок>
End;
Если какая-либо инструкция в теле макропроцедуры Test или инструкция в процедурах,
вызванных из Test, генерирует ошибку времени выполнения, то управление передается на
первую инструкцию для обработки ошибок после ключевого слова OnError, и аварийного
завершения RSL-программы не происходит.
В случае, когда обработчику нужна информация о произошедшей ошибке, после
ключевого слова OnError в скобках необходимо указать имя переменной (эта переменная не
должна декларироваться в теле макропроцедуры при помощи ключевого слова var), которая
после возникновения сбоя получит ссылку на специальный объект класса TrslError,
содержащий информацию о данной ошибке. Свойства объекта класса TrslError приведены в
Таблице 1.
Таблица 1. Свойства объекта класса TrslError
Свойства
Code
Message
Module
Line
Описание
код ошибки
строка, описывающая ошибку
название модуля RSL, вызвавшего ошибку
строка в модуле, в которой произошла ошибка
Macro Test2
<инструкции RSL>
OnError ( er )
MsgBox (er.Message,»| Модуль: »,er.Module,«| строка: «,er.Line)
End;
14
Чтобы в обработчике принудительно сформировать некоторую ошибку для передачи ее
другому обработчику в цепочке вызовов макропроцедур или обработчиком RSL по
умолчанию, необходимо вызвать стандартную RSL-процедуру RunError без параметров.
Следует обратить внимание, что модуль RSL представляет собой разновидность
макропроцедуры, у которой отсутствует имя и ключевое слово «Macro» в начале. А вот
заканчиваться модуль может так же, как и макропроцедура, — ключевым словом «end».
Поэтому в макромодуле, как и в макропроцедуре, можно реализовать обработчик ошибок.
Ключевое слово «end» по-прежнему не обязательно. Приведем пример.
Import rslx;
Macro Test
…..
end;
OnError (er)
MsgBox (er.Message)
End
/* End может отсутствовать */
* * *
Таковы новые возможности Object RSL. Чтобы определить, доступны ли они в той
версии языка, которую используете Вы, вызовите RSL-процедуру Version. Если она
возвратит число большее или равное 852, все примеры из настоящей статьи будут работать и
у Вас. Кроме того, приведенные примеры относятся также и к среде Visual RSL.
Единственное отличие: в Visual RSL не требуется включать в тексты программ модуль rslx
— это делается автоматически, вследствие чего вся функциональность данного модуля
доступна в любое время.
15
Related documents
Download