Реализация обработчика событий
Обработчик событий – это внутренняя процедура. Процедуры обработки событий можно добавить в файл вызываемой процедуры или разместить их в качестве внутренних процедур в отдельном файле внешней процедуры. В наших примерах мы будем использовать файл внешней библиотеки процедур для хранения обработчиков событий.
Описание обработчиков событий в качестве внутренних процедур во внешней процедуре позволяет удобно хранить код, связанный с обработкой событий конкретного набора данных в едином файле.
Для реализации обработчика событий набора данных необходимо:
- Создать файл внешней процедуры для хранения кода процедур обработки событий набора данных.
- Написать код обработки событий.
- В коде заполнения или изменения набора данных связать процедуры обработки событий с набором данных или временными таблицами.
В следующем примере показано содержимое файла внешней библиотеки процедур (.p), где размещены несколько обработчиков событий набора данных, представленных в виде внутренних процедур.
ROUTINE-LEVEL ON ERROR UNDO, THROW. {<INCLUDE-FILE>} PROCEDURE <PROCEDURE-NAME1>: DEFINE INPUT PARAMETER DATASET FOR <DATASET-NAME>. /* Код для обработки события */ END PROCEDURE. PROCEDURE <PROCEDURE-NAME2>: DEFINE INPUT PARAMETER DATASET FOR <DATASET-NAME>. /* Код для обработки события */ END PROCEDURE.
Здесь:
<INCLUDE-FILE> | Встраиваемый файл с описанием набора данных. |
<PROCEDURE-NAME> | Название процедуры обработки события, которое должно быть уникальным в пределах файла. |
<DATASET-NAME> | Название набора данных, описанного во встраиваемом файле. Каждая процедура обработки события должна иметь единственный входящий параметр, который является набором данных, независимо от типа события. |
После того, как мы создали внутренние процедуры для обработки событий, мы должны связать каждый обработчик и именованное событие с конкретным набором данных, буфером временной таблицы или объектом запроса в коде, который заполняет или обновляет набор данных. Сначала мы должны загрузить файл внешней процедуры, который содержит внутренние процедуры, в качестве персистентной процедуры в AVM. Затем связать каждую процедуру обработки событий с соответствующим объектом набора данных, для чего применяется метод SET-CALLBACL-PROCEDURE ().
Следующий синтаксис используется для написания кода загрузки внешней процедуры в AVM путём её вызова и привязки к переменной с типом HANDLE.
/* Описываем переменную для хранения хэндла процедуры */ DEFINE VARIABLE <PROC-HANDLE-NAME> AS HANDLE NO-UNDO. . . . /* Устанавливаем хэндл внешней процедуры */ RUN <PROC-FILE-NAME> PERSISTENT SET <PROC-HANDLE-NAME>. . . . /* Связываем внутреннюю процедуру с именованным событием*/ <OBJECT-TYPE> <OBJECT-REFERENCE>:SET-CALLBACK-PROCEDURE("<EVENT-NAME>","<PROCEDURE-NAME>",<PROC-HANDLE-NAME>).
Здесь:
<PROC-HANDLE-NAME> | Переменная типа HANDLE для персистентной процедуры. |
<PROC-FILE-NAME> | Название файла процедуры (.p). Этот файл должен быть доступен по PROPATH. |
<OBJECT-TYPE> | Тип данных ABL, который может быть dataset, buffer или query. |
<OBJECT-REFERENCE> | Ссылка на объект dataset, temp-table или query. |
<EVENT-NAME> | Название события набора данных: BEFORE-FILL, AFTER-FILL, BEFORE-ROW-FILL, AFTER-ROW-FILL, ROW-CREATE, ROW-UPDATE, ROW-DELETE, FIND-FAILED, OFF-END или SYNCHRONIZE. |
<PROC-NAME> | Название внутренней процедуры, описанной в файле <proc-file-name> в качестве обработчик события набора данных. |
Следующий пример кода используется на сервере для заполнения набора во время выполнения. В нём описан хэндл для процедуры с обработчиками событий. Затем внешняя процедура загружается в качестве персистентной и устанавливается хэндл этой процедуры. После чего временная таблица ttOrder связывается с обработчиком AdjustCarrier() для события AFTER-ROW-FILL.
DEFINE VARIABLE hEventHandlers AS HANDLE NO-UNDO. RUN BusinessData/DSEventHandlers PERSISTENT SET hEventHandlers. BUFFER ttOrder:SET-CALLBACK-PROCEDURE( "AFTER-ROW-FILL","AdjustCarrier", hEventHandlers).
Примечание: после завершения работы с персистентной процедурой и при условии отсутствия необходимости в ней в будущем, чтобы избежать утечек памяти всегда удаляйте такую процедуру оператором DELETE PROCEDURE.