Содержание материала

 

Таким образом, мы реализовали полную функциональность по трансляции вызовов OLE в обращения к свойствам VCL. Наш компонент может динамически создавать другие компоненты на форме, обращаться к их свойствам и даже обрабатывать возникающие в них события.

 

Оператор For Each

Удобным средством, предоставляемым VBScript, является оператор For Each, организующий цикл по всем элементам заданной коллекции. Добавим поддержку этого оператора в наш компонент.

 

Интерфейс IEnumVariant

Реализация For Each предусматривает следующее:

1. Исполняющее ядро ScriptControl вызывает метод Invoke объекта, по элементам которого должен производиться цикл с DispID = DISPID_NEWENUM (-4).
2. Объект должен вернуть интерфейс IEnumVariant
3. Далее ядро использует методы IEnumVariant для получения элементов коллекции.

Интерфейс IEnumVariant определен как:

 

Code:

type

IEnumVariant = interface(IUnknown)

   ['{00020404-0000-0000-C000-000000000046}']

   function Next(celt: LongWord; var rgvar: OleVariant;

     pceltFetched: PLongWord): HResult; stdcall;

   function Skip(celt: LongWord): HResult; stdcall;

   function Reset: HResult; stdcall;

   function Clone(out Enum: IEnumVariant): HResult; stdcall;

end;

 

 

 

В модуле ActiveX.pas в оригинальной поставке Delphi5 ошибочно определен метод Next

 

Code:

function Next(celt: LongWord; var rgvar: OleVariant;

    out pceltFetched: LongWord): HResult; stdcall;

 

 

поэтому для корректной реализации интерфейс должен быть переопределен.

 

Класс TVCLEnumerator

Создадим класс, инкапсулирующий функциональность IEnumVariant

 

Code:

type

TVCLEnumerator = class(TInterfacedObject, IEnumVariant)

private

   FEnumPosition: Integer;

   FOwner: TPersistent;

   FScriptControl: TVCLScriptControl;

   { IEnumVariant }

   function Next(celt: LongWord; var rgvar: OleVariant;

     pceltFetched: PLongWord): HResult; stdcall;

   function Skip(celt: LongWord): HResult; stdcall;

   function Reset: HResult; stdcall;

   function Clone(out Enum: IEnumVariant): HResult; stdcall;

public

   constructor Create(AOwner: TPersistent;

     AScriptControl: TVCLScriptControl);

end;

 

Конструктор устанавливает свойства FOwner и FScriptControl

 

Code:

constructor TVCLEnumerator.Create(AOwner: TPersistent;

AScriptControl: TVCLScriptControl);

begin

inherited Create;

FOwner := AOwner;

FScriptControl := AScriptControl;

FEnumPosition := 0;

end;

Метод Reset подготавливает реализацию интерфейса к началу перебора

function TVCLEnumerator.Reset: HResult;

begin

FEnumPosition := 0;

Result := S_OK;

end;

 

 

Добавить комментарий

Не использовать не нормативную лексику.

Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить