Модель подієво-керованого застосування
Давайте зведемо воєдино те, що визначає модель подієво- керованого застосування в FoxPro. Програмування подієво- керованого застосування в основі своїй має на увазі, що ви можете мати на екрані комп'ютера кілька екранів, і при перемиканні між ними за допомогою миші відбувається активізація коду, який керує роботою кожного екрану. Якщо екран закритий іншими, ви можете використовувати меню для виклику його наверх. Екран існує до тих пір поки користувач не закриє його. Додаток очікує виникнення деякого "події" (вибору опції меню, клацання миші), це і дає ім'я терміну "подієво- кероване".
На відміну від Visual Basic або Clipper 5.0 FoxPro не входить в стан очікування події сам по собі. Вам необхідно створити цей стан. Це робиться використанням команди READ.
READ очікує введення даних в поле, створене командою @. GET. як це було завжди, але крім того, команда готова до реакції на будь-яку подію, яка потенційно прагне завершити її. Саме для обробки такої події існує пропозиція VALID.
Якщо ми використовуємо конструкцію READ VALID func (). то READ залишається активною до тих пір поки func () не поверне. Т. (Істина). До тих пір додаток може перекидати управління подібно волейбольному м'ячу. На цьому, правда, простота закінчується. Починаючи з цього моменту ситуація починає ускладнюватися.
При виборі опції меню FoxPro виконує пов'язану з нею команду або процедуру. Однак немає гарантії, що будь-яке ваше дію викличе спрацьовування логіки, пов'язаної з пропозицією VALID. при команді READ. Виявляється, вам потрібно подбати і про це. При натисканні мишею на вікні, розташованому не на самому верху, вам потрібно відшукати і запустити відповідний .SPR -модуль. FoxPro не пропонує механізму, що дозволяє зробити це автоматично. Тим не менш, є кілька точок, де ви можете втрутитися в природний хід подій і направити їх у зручний для вас русло.
Одна з таких точок забезпечується пропозицією READ DEACTIVATE в .SPR -модулем. Генератор екранів FoxPro постачає кожен екран або набір екранів командою READ. до якої ви можете причепити блоки коду. Ці блоки зв'язуються з пропозиціями, які можуть бути використані спільно з READ: SHOW, SETUP, CLEANUP, ACTIVATE і DEACTIVATE. Ці пропозиції складають першу частину ключа до програмування подієво-керованих додатків в FoxPro, READ VALID - друга його частина, але про це ми поговоримо пізніше.
Коли GENSCRN виконує генерацію коду, інсталяційний блок команд (Setup Code) розміщується на самому початку створюваної програми, а закриває блок (Cleanup Code) потрапляє в самий кінець. В середині SPR-файлу генератор поміщає команди GET. за якими слід READ. READ може мати до трьох пропозицій, кожному з яких може відповідати блок коду або виклик процедури.
Код, пов'язаний з пропозицією SHOW. виконується кожен раз при виконанні команди SHOW GETS. так що сюди доречно вставити логіку, яка оновлює вміст поточного екрана. Якщо у вас нічого оновлювати крім вмісту полів GET. залиште цю пропозицію порожнім. Однак, для подієво- керованих додатків код, пов'язаний з пропозиціями ACTIVATE і DEACTIVATE. стає виключно важливим.
Код, пов'язаний з ACTIVATE. виконується кожен раз при спробі вивести відповідний екран наверх, зробити його активним. У тому випадку якщо ваша програма має елементи управління для переміщення по записах, то цілком можливо, що ви вставите код, який гарантує вам перехід на потрібну робочу область для цього екрану, що-небудь на зразок SELECT <имя рабочей области>. Це найбільш часто зустрічається використання пропозиції ACTIVATE і часто єдине.
DEACTIVATE навпаки грає виключно важливу роль при створенні подієво-керованих додатків. Спробуйте таку штуку: запустіть FoxPro, визначте пару вікон і активізуйте обидва. Тепер по черзі клацніть на кожному з вікон і відкривши меню Window (Alt + W) подивіться, що робиться з порядком перерахування імен ваших вікон. Ви побачите, що порядок змінюється. Саме в цьому полягає підхід до побудови подієво - керованих додатків.
У багатьох подієво-керованих додатках ви знайдете функцію, яка читає список імен вікон для визначення останнього елемента. Навіщо? Невже не можна використовувати функцію WONTOP (). Можна, якщо ви не використовуєте набори екранів (screen sets). Зараз поширеною практикою стало використання єдиного вікна з елементами управління для переходу між записами, перемиканням між режимами і т. П. Для отримання такої функціональності вам необхідно створити набір екранів, що складається з вікна Control і вашого вікна, після чого в код, пов'язаний з пропозицією ACTIVATE . обов'язково потрібно додати наступні рядки:
ACTIVATE WINDOW (ім'я вашого вікна)
ACTIVATE WINDOW CONTROL
В результаті виходить, що ваше вікно не розташовується зверху, воно передостаннє. (На практиці ви прочитуєте список вікон зверху вниз, зберігаючи імена вікон крім імені Control).
Аналогічно немає красивого способу визначити, яке вікно щойно було закрито. Тому загальноприйнятим став прийом, коли ім'я закривається вікна передається як параметр через код в READ DEACTIVATE.
Як же робиться це подієво-кероване програмування? По-перше, ми припускаємо, що до тих пір поки на екрані не з'явилося хоча б одне активне вікно, користувач буде відкривати вікна, вибираючи їх з меню. Використовуємо команду:
ON SELECTION BAR 1 OF database DO nextprog WITH 'Contact.Spr'
У прикладену програму входить функція NextProg. представлена в лістингу 14-1 і в кінці лістингу 14-3.
Це означає, що "якщо в даний момент немає активної процедури, запускаємо ту, що була обрана з меню, в іншому випадку міняємо значення змінної NextProgram і видаємо CLEAR READ".
NextProgram називається "чергою подій". У складних додатках, таких як Tom Rettig's Office. чергу подій може бути багаторівневою, вам може бути необхідно виконати кілька обов'язкових дій при завершенні певного режиму і саме тут потрібно створити механізм визначення дій в залежності від вашого становища. Подієво - - кероване програмування не для слабаків. У нашому простому прикладі, проте, чергу теж нескладна.
Навіщо CLEAR READ. Чому не можна просто DO (NewProgram). Причина в тому, що вам потрібно почистити за поточним завданням, і CLEAR READ примушує до виконання пропозиції READ VALID. Такий підхід дозволяє вам направити всі процедури модифікації екрану через єдиний канал.
Процедура, що виконується за READ VALID. називається Events. Вона представлена в лістингу 14-2.
Відбутися можуть три взаємовиключних події:
1) виконання програми закінчено - користувач вибрав Вихід в меню;
2) користувач вибрав інший режим роботи в меню;
3) користувач клацнув мишею на вікні.
У нашому прикладі використовуються імена вікон, що закінчуються цифрою, я вчинив так для спрощення коду в READ VALID. Якщо вікно має ім'я multiwin. тоді MultiRead включає номер вікна, який може бути використаний для відновлення імені вікна. Це спрощує читання коду. У ваших програмах може і не бути пов'язані в групи вікон, але якщо вони є, то мій метод працює цілком пристойно.
Ось як працює подієво-кероване додаток в FoxPro. В Visual FoxPro вам може і не доведеться продиратися через всі ці складності. Поки ж це робиться саме так.
Варіації на ту ж тему
Я розробив кілька варіантів підходу до створення подієво- керованих додатків і думаю, що вони виявляться цікавими і корисними. Ці варіанти описані в наступних розділах.
CLEAR READ призводить до примусового виконання коду, пов'язаного з READ VALID в foundation READ. Чому б не використати одне і те ж ім'я вікна в декількох .SPR файлах і просто викликати різні програми без створення нового вікна? Я спробував і через кілька хвилин отримав працюючу модель.
Приклад включає три файли Contact1, Contact2, Contact3. Вікно має ім'я Contact у всіх трьох екранах. Пам'ятайте, що GenScrn створює код такого виду:
IF WVISIBLE ( "contact")
ACTIVATE WINDOW contact SAME
ELSE
ACTIVATE WINDOW contact NOSHOW
ENDIF
. деякий код.
IF NOT WVISIBLE ( "contact")
ACTIVATE WINDOW contact
ENDIF
Для виклику наступної "сторінки" зробіть так:
NextProgram = "Contact3.Spr"
CLEAR READ
У нашому прикладі GET повинні займати певні позиції щоб уникнути накладень. Якби не це я вчинив би так:
IF WONTOP () = "CONTACT"
ACTIVATE WINDOW contact SAME
@ 10,1 CLEAR TO 15,57
ENDIF
Ще один підхід ви можете знайти якщо подивіться код, який організовує висновок декількох екранів, коли користувач вибирає опцію About з основного меню.
Один з методів підтримки батьківських-дочірніх файлів передбачає зміну розмірів масиву з даними з дочірніх записів і виведення результатів в найпотужнішому з нових GET - об'єктів - прокручування списків. Модифікація масиву виробляється в процедурі, пов'язаної з пропозицією SHOW в батьківському екрані.
FOR i = 1 TO nActivCnt
aActivity [i, 6] = DTOC (aActivity [i, 2]) + "|" +;
aActivity [i, 3] + "|" +;
aActivity [i, 4] + "|" +;
aActivity [i, 5]
ENDFOR
(Те ж саме можна отримати однією командою на SQL, яка до того ж може бути і швидше - прим. Пер.):
SELECT ACTIVITY.AID, ACTIVITY.DATE, ACTIVITY.TIME, ACTIVITY.TYPE ,;
ACTIVITY.CONTACT, DTOC (ACTIVITY.DATE) + '| '+ ACTIVITY.TIME +' | '+;
ACTIVITY.TYPE + '| '+ ACTIVITY.CONTACT;
FROM ACTIVITY, CONTACT;
WHERE CONTACT.ID = ACTIVITY.ID;
INTO ARRAY aActivity
Для прокручується при створенні екрану потрібно позначити опцію 1st Element і ввести вираз (Expression) 6 (шостий елемент отриманого масиву повинен бути виведений в список). Після чого можна вибравши елемент зі списку знайти відповідний запис в дочірньому файлі.
Код в реченні VALID виглядає так:
IF nActivCnt> 0
SELECT activity
LOCATE FOR aid = Aactivity [nActivity, 1]
ENDIF
NextActivity = .T.
NextProgram = "activity.spr"
CLEAR READ
При цьому ми можемо знайти дочірню запис, якщо вона існує, або додати нову.
FoxPro 2.0 має кілька директив генератора - команд, які керують генерацією коду. У версії 2.5 додано кілька інших директив, деякі з них досить до речі.
Подієво-керовані програми FoxPro завжди мали величезну кількість повторюваного коду. Установчі та закривають частини програм створення екранів були якщо не зовсім однаковими, то, у всякому разі, дуже схожими. Версія 2.5 пропонує нову директиву, який скорочує небезпеку помилки при багаторазовому введенні одного і того ж коду або при його копіюванні - це директива #INSERT.
Нова директива - чудовий інструмент. Якщо установчі, що закривають, перевіряючі і ін. Ділянки програм мають загальну функціональність вам достатньо написати код тільки один раз. У наводиться прикладі (Лістинг 14-3) я пропоную кілька стандартних процедур setup.gen (процедура установки), show.gen (процедура поновлення змінних на екрані), так само як і кілька специфічних для додатка, але повторюваних ділянок коду - contact.set (установча частина коду) і contact.cln (завершальна частина коду). При необхідності змінити роботу додатка вам потрібно тільки внести корективи в кілька стандартних модулів.
Врахуйте тільки, що зміна коду в стандартних процедурах не змусить менеджер проектів заново згенерувати код для створення екранів. Після внесення змін вам потрібно заново зібрати проект із зазначеною опцією [] Build All. Можна також видалити .SPR файли, в які повинні потрапити змінені модулі, але це легко забути.
Я запропонував вам кілька підходів. Упевнений, що ви знайдете безліч інших рішень.