Поддержка MS-макросов в DELPHI
С чего начать
Конечно, выбор, как всегда, есть.
Самый трудный путь - это написание собственного интерпретатора
макрокоманд. Естественно, возиться с написанием собственных
разборщиков синтаксиса, исполнителей команд и т.д., не каждый
захочет - вот если бы найти такой компонент, который принимал
бы исходный текст макроса и выводил результат. К счастью
несчастных программистов и здесь на помощь пришла всеми
любимая Microsoft, разработавшая Windows Script Control -
компонент, который соответствует практически всем требованиям,
выдвигаемым к поддержке макросов в ваших программах.
Итак, для
начала нам понадобится сам компонент Windows Script Control,
который можно загрузить с сайта разработчика (название архива
- sct10en.exe). Распаковав его, мы увидим собственно компонент
msscript.ocx и дополнительные файлы справки.
Теперь
смело можно браться за разработку поддержки макросов в вашем
приложении.
Пример 1
К этому времени вы уже запустили среду разработки (которая,
естественно, должна поддерживать работу с ActiveX, к примеру,
Delphi) и создали новое приложение (New > Application).
Теперь нужно импортировать данные из библиотеки msscript.ocx в наш
проект. Для этого воспользуемся пунктом меню Project >
Import Type Library - и для достоверности выберем нашу
библиотеку, щелкнув на кнопке Add…(рис. 1). После чего выберем
файл msscript.ocx.
Импортировав библиотеку, мы обнаружим в составе нашего
проекта файл MSScriptControl_TLB.pas, в котором содержатся все
необходимые определения интерфейсов и констант. Теперь в
главной форме нашего приложения, в реакции кнопки (которую мы
уже разместили на форме), напишем следующий код:
procedure TForm1.Button2Click (Sender:
TObject); var
SC:TScriptControl; Code:WideString; begin SC:=TScriptControl.Create
(Self); SC.Language:='VBScript'; try Code:='Function
DoSmth () '#13#10+ 'DoSmth = "This is the Simple
Test"'#13#10+ 'End Function'; SC.AddCode
(Code); SC.ExecuteStatement ('MsgBox "Testing:"+DoSmth
()'); finally SC.Free; end; end;
После
выполнения этого кода увидим на экране сообщение системы
(Testing:This is the Simple Test).
Теперь
рассмотрим приведенный выше код более подробно. Сначала
создаем объект TScriptControl, который, собственно, и
проделывает за нас всю грязную работу. Далее присваиваем
свойству Language значение "VBScript", уведомляя тем самым
компонент о том, что переданный ему код будет написан на
Visual Basic. Помимо VBScript: тут возможны и другие значения:
можно, например, воспользоваться Jscript - при этом будет
использован синтаксис JavaScript или же синтаксис любого
другого интерпретатора, поддерживающего технологию
ActiveX-скриптов (Visual Basic, Java, ActivePython, ActivePerl
и т.п).
В следующих строчках пишем исходный код функции DoSmth, которая
возвращает нам вторую часть предложения. Далее записываем этот
код в компонент - а в следующей строчке исполняем его,
передавая возвращаемое им значение в функцию MsgBox. Все это
пишется с использованием синтаксиса Visual Basic. Функции
AddCode и ExecuteStatement имеют следующий вид:
procedure AddCode (const Code: WideString);
safecall;
Где Code - код процедуры, функции (или любого их сочетания в любом
количестве), который записывается в компонент и после этого
может быть вызван с помощью ExecuteStatement или Run:
procedure ExecuteStatement (const Statement:
WideString); safecall;
Где Statement - текст программы, который будет сразу же
исполнен.
Пример 2
Осуществлять вывод сообщений при помощи макроязыка мы
уже научились, однако это не единственная возможность
компонента. Так, компонент TScriptControl представляет нам
возможность использования собственной объектной модели в
создаваемых макросах - то есть доступ к специфическим объектам
нашего приложения. Для этого в нашем приложении потребуется
сначала создать объект автоматизации Automation Object
(пользователи Microsoft Visual Basic могут пропустить этот
раздел, так как в Visual Basic поддержка объектов
автоматизации встроена изначально). Чтобы создать этот объект,
при открытом приложении щелкнем на пункте меню Новый и выберем
закладку ActiveX. Здесь выберем пункт Automation
Object.
Далее предстоит создать интерфейс, который мы
собираемся включить в объектную модель ScriptControl. Для
начала просто создадим объект с единственной функцией print,
которая будет выводить в компонент TlistBox, размещенный на
главной форме, некоторый текст. Все существенные настройки
показаны на рис. 2.
Далее обновляем информацию об объекте, щелкнув для этого на
соответствующей кнопке (рис. 2), и переходим к секции
реализации объекта.
Здесь уже нас поджидает созданный средой разработки шаблон, в который
остается внести только некоторые исправления:
unit SimpleTest;
{$WARN SYMBOL_PLATFORM OFF}
interface
uses ComObj, ActiveX, ScriptTest_TLB,
StdVcl;
type TSimpleTest = class (TAutoObject,
ISimpleTest) protected procedure Print (Data:
OleVariant); safecall; {Protected
declarations} end;
implementation
uses ComServ,Main;
procedure TSimpleTest.Print (Data:
OleVariant); begin Main.Form1.ListBox1.Items.Add
(Data); end;
initialization TAutoObjectFactory.Create
(ComServer, TSimpleTest, Class_SimpleTest, ciMultiInstance,
tmApartment); end.
Осталось
один раз прогнать наше приложение вхолостую - для регистрации
и проверки на наличие ошибок. Если все прошло удачно, можно
приступать к дальнейшему написанию макросов.
Регистрация объекта
Как и в прошлый раз, создадим на нашей главной форме кнопку и объект
ListBox1. Затем в реакцию кнопки на нажатие напишем следующий
код:
procedure TForm1.Button1Click (Sender:
TObject); var
SC:TScriptControl; Test:ISimpleTest; begin SC:=TScriptControl.Create
(Self); Test:=CoSimpleTest.Create; try SC.Language:='VBScript'; SC.AddObject
('PrintTest',Test,True); SC.ExecuteStatement
('PrintTest.Print "This is the
Test"'); finally Test:=nil; SC.Free; end; end;
Опять же,
как и в прошлый раз, сначала создаем компонент ScriptControl,
затем инициализируем интерфейс ISimpleText и добавляем его в
нашу объектную модель посредством функции:
procedure AddObject (const Name: WideString;
const Object_: IDispatch; AddMembers: WordBool);
safecall;
Где:
Name - название нашего компонента во
внутреннем пространстве имен. Object -
ссылка на наш объект. AddMembers -
опциональный параметр, который устанавливается в True, если
все члены класса Object должны быть доступны глобально, и
False - в противном случае.
Следующая
строка кода демонстрирует использование объекта Test при
написании макроса. Как видно, в тексте макроса мы пользуемся
названием, определенным при помощи параметра Name функции
AddObject. Результат - на рис. 3.
Послесловие
Встроенный
макроязык - это то средство, которое может превратить вашу
программу в мощный и универсальный продукт. Но имейте в виду,
что показанная техника - только вершина айсберга, в составе
библиотеки имеется еще много компонент (IScriptError,
IScriptModule, IScriptModuleCollection, IScriptProcedure,
IScriptProcedureCollection), которые позволяют всесторонне и
тонко управлять интерпретатором.
Некоторые методы и свойства
компонента ScriptControl
- AddCode. Запись в компонент исходных
текстов процедур и функций для последующего их выполнения.
- AddObject. Добавление объекта к
внутренней объектной модели макросов.
- Eval. Выполнение вычисления и возврат
результата. То же что и if в нормальных языках
программирования.
- ExecuteStatement. Немедленное
выполнение представленного кода.
- Reset. Восстановление первоначального
состояния интерпретатора. Очистка от всех предыдущих
исходных кодов.
- Run. Выполнение предопределенной при
помощи AddCode процедуры или функции с заданными
параметрами.
- OnError. Событие, возникающее при
ошибке времени выполнения.
- OnTimeOut. Событие, возникающее при
таймауте.
Автор: Михаил Продан
Источник: www.cpp.com.ua
|