1. Запуск форми, FoxPro, Бази даних, статті

Зазвичай запуск форм здійснюється за допомогою тривіальної команди DO FORM
<Імя_форми>
з коду програми або ж у командному вікні середовища розробки
VFP, а також шляхом вибору потрібної форми в менеджері проектів на закладці
Documents і натисканням кнопки Run (Або ж з меню середовища розробки).
Ось тут і може виникнути одна "тонкість". Звичайно, форма в найпростішому
випадку може бути незалежною від інших об'єктів створюваного застосування або
інших умов. Але це тільки в самому простому випадку. Найчастіше ситуація
складається зовсім по іншому – форма запускається з меню або з іншої форми.
Форми повинні вміти "розмовляти" один з одним, обмінюватися інформацією. В
загальному випадку запуск форми ставитися в залежність від ряду умов, параметрів
або від інших форм. Ось тут і приходить на допомогу метод відомий як принцип
вільних зв'язків. Звичайно, це не є панацея і не є обов'язковим для
застосування у всіх випадках, але це варто взяти на озброєння як хорошу техніку
програмування. Полягає він у тому, що форма повинна мати можливість
запуску не тільки в конкретному місці з конкретними умовами, а й сама по собі
(Хоча б у разі тестування) незалежно від вимог, що накладаються
додатком і вміти функціонувати в надзвичайних ситуаціях. Як приклад
розглянемо можливу організацію вашого програми:


  1. У програмі є деякий "менеджер" форм, який відповідає за запуск
    форм, їх станом, доступністю, закриттям і т.п.
  2. Цей менеджер має якийсь метод DoForm () для запуску і установки зв'язків
    між формами і самим додатком
  3. Менеджер завжди встановлює посилальну зв'язок для того, щоб легко можна
    було обмінюватися даними чи повідомленнями між формами і самим менеджером
    за допомогою переданих параметрів.

Для того щоб здійснити такий задум, як ви розумієте варто завести
клас форми з методом
DoForm(), Який буде передавати ім'я форми і
інші необхідні параметри менеджеру форм, повідомляти йому, яку форму потрібно
запустити. Цілком припустимо передавати не тільки ім'я форми, а й саму посилання на
форму, для цього можна сміливо використовувати слово THISFORM.

 * Init() Method
LPARAMETERS toFormManager
IF toFormManager) = ""O""
ThisForm.oFormManger = toFormManager
ENDIF

* DoForm() Method
LPARAMETERS tcFormName, tuParm1, tuParm2
IF VARTYPE (ThisForm.oFormManager) = "" O "";
AND NOT ISNULL(ThisForm.oFormManager)
ThisForm.oFormManger.DoForm(tcFormName,tuParm1,tuParm2)
ELSE
DO CASE
CASE PCOUNT() = 1
DO FORM (tcFormName) WITH .NULL.
CASE PCOUNT() = 2
DO FORM (tcFormName) WITH .NULL., tuParm1
CASE PCOUNT() = 3
DO FORM (tcFormName)WITH .NULL.,tuParm1,tuParm2
ENDCASE
ENDIF


Вся родзинка тут полягає в тому, що форма може запускатися, використовуючи
цей менеджер форм, але в теж час здатна працювати і без нього. Цей приклад
показовий тим, як можна будувати універсальні, на предмет залежності від
зовнішніх умов, форми. Розробник повинен досить серйозно ставитися до
цього питання хоча б тому, що зазвичай на етапі розробки форми робляться в
якоїсь черговості, і не завжди до кінця, але кожна з них потребує незалежному
від інших форм тестуванні, які можуть до даного моменту або не
існувати, або бути вельми "сири".

2. Іменування форм.


За замовчуванням запущена форма приймає ім'я файлу з розширенням .scx в
якому вона власне зберігається. Однак всередині програми, якщо не прийняти
спеціальних заходів, вона відома з цього імені тільки в колекції форм
змінної
_SCREEN. Але це ім'я можна змінити, явно вказавши ім'я
командою під час запуску форми.

  DO FORM MyForm NAME frmMyForm

причому виконавши команду

  DO FORM MyForm NAME frmMyForm2

отримаємо другий примірник форми, але з іншим ім'ям.

Необхідно звернути увагу на ще один аспект команди DO FORM
виконання її з ключовим словом LINKED:

  DO FORM MyForm NAME frmMyForm2 LINKED

У цьому випадку форма MyForm асоціюється з
змінної frmMyForm2, І тепер звертатися до властивостей і методів
форми можна за допомогою цієї змінної:


frmMyForm2.Caption = 'Це заголовок форми'

Особливістю такого запуску є те, що форма MyForm буде
закрита при звільненні змінної frmMyForm2. Часто таку змінну
визначають як public ще до запуску форми. При цьому, якщо з форми вийшли
звичайним способом, для ясності потрібно або очистити змінну або також звільнити
її – виконати RELEASE frmMyForm2.

Якщо змінна локальна, то закриття форми гарантується після закінчення
виконання методу або процедур, в якому створювалася змінна. Слід
зауважити, що форма (так само як і будь-який об'єкт) не може бути
закритапоки не закінчено виконання якого або її методу або ж є
посилання на неї в якому то з об'єктів програми. Визначення public або
local відразу для всіх викликаних пізніше форм дозволяють не стежити, яка
форма викликана першою, а яка після неї, і тим самим полегшують організацію
обміну між формами.

Розглянемо так само ситуацію, коли форма не модальна і запущена без асоціацій
з методу (або події) будь-якої форми:

  DO FORM MyForm NAME MyStartedForm

Перевизначити ім'я знову запущеної форми в межах цього методу (оскільки
змінна MyStartedForm буде звільнена після виконання методу і
стане недоступною)

  MyStartedForm.Name="MyFormWithNewName"

Тепер, для того щоб отримати доступ до цієї запущеній формі звернемося до
колекції форм об'єкта _Screen і виконаємо пошук:

  LOCAL lnFormCount, lnFindForm
lnFindForm=0

FOR lnFormCount = 1 TO _SCREEN.FORMCOUNT
IF _SCREEN.FORMS (lnFormCount). NAME = "MyFormWithNewName"
lnFindForm= lnFormCount
EXIT
ENDIF
ENDFOR


Якщо форма знайдена і lnFindForm>0 , Можна звертатися до форми через
елемент колекції _Screen :

 _SCREEN.FORMS (LnFindForm). Caption = "Та сама форма"
_SCREEN.FORMS(lnFindForm).SomeMethod()

Ці операції з пошуку форми в колекції через її ім'я можна виділити в
окрему процедуру або метод об'єкта програми (якщо такий є) в
власному наборі класів або ж у вже згаданому менеджері форм. Варто врахувати,
що пошук форми необхідно виробляти безпосередньо перед зверненням до
ній, оскільки індекс форми в колекції динамічно змінюється при запуску або
закритті форм у додатку.

Іноді бувають ситуації, коли потрібно звернутися до форми у відриві від її
контексту, наприклад у методі глобального об'єкта програми або при зверненні з
кнопки тулбара, коли звернення THISFORMне може бути застосоване.
У цьому випадку також можна звернутися до форми через колекцію _Screen:

 _Screen.ActiveForm.Caption = "Це і є активна форма"
_Screen.ActiveForm.SomeMethod()

Раз вже згаданий тулбар, ясно, що в ньому можуть бути різні клавіші з різною
функціональністю – зберегти, скасувати, новий запис, знайти і інші. Всі ці
клавіші аналогічним чином можуть викликати методи активною в даний час форми.
Однак, далеко не всі форми є однотипними, які то можуть бути тільки
формами пошуку без можливості введення, інші навпаки, тільки вводити
інформацію. Тому у уникнення помилкової ситуації кнопки тулбара повинні вміти
перевірити, а чи є на активною в даний час формі потрібний їм для роботи
метод, скажімо так –

 If type ('_Screen.ActiveForm') = 'O' and pemstatus (_Screen.ActiveForm, 'DoSomthing', 5)
_Screen.ActiveForm.DoSomething
endif

У формі, що вимагає параметрів, у методі Init() проводять їх опис
командою LPARAMETERS.

Саме туди потрапляють параметри, передані при запуски форми з опцією
WITH. Запуск такої форми виглядає наступним чином:

 * Метод Init () форми MyForm
LPARAMETERS lcNewCaption
If !empty(lcNewCaption)
Thisform.Caption= lcNewCaption
Endif

* Запуск форми
DO FORM MyForm WITH "Новий заголовок форми"


Іноді потрібно запустити форму, але до настання певних умов вона
повинна бути скрита.Напрімер, таке потрібне при запуску модальної форми, коли
відразу після її виклику, але до реального появи на екрані, потрібно викликати
деякі методи цієї форми або відразу змінити значення будь-яких властивостей. Це
дозволяє одну й ту ж форму зробити більш гнучкою, яка працює і в режимі
модальності і здатною бути немодальному, а отже і уникнути
виготовлення більшої кількості близьких за видом форм. Використовуйте для цього опцію
NOSHOW

  DO FORM MyForm NOSHOW

При запуску форми з меню буває необхідно виключити повторний її запуск.
Для цього можна застосувати такий трюк – якщо в опціях пункту меню в дбав
Skip Forнаписати WEXIST ("імя_форми"), То при
запуску форми пункт меню стане недоступним до її закриття. Таким чином
виключається повторний запуск бажаної форми. Правда варто враховувати те, що якщо
в процесі виконання програми ім'я форми змінитися, пункт відновить свою
доступність. Хоча мені здається, що таких трюків варто уникати, якщо хочеться
мати по-справжньому мульти документний інтерфейс.

3. Послідовність подій у формі.


Форма в чистому вигляді, без елементів управління і даних, які вона повинна
маніпулювати, інтересу не представляє. Тому будь-яка форма створюється саме з
метою оперування даними за допомогою елементів управління, що включаються у форму.
Дані в VFP зберігаються, природно, в таблицях і підключаються до форми за допомогою
спеціального об'єкта Data environment. Розглянемо послідовність
подій при запуску форми, але зупиняючи увагу поки тільки на подіях
самої форми. Об'єкт – Подія


  • Data environment – BeforeOpenTables
  • Form set – Load
  • Form – Load
  • Data environment cursor(s) – Init
  • Data environment – Init
  • Objects – Init
  • Form – Init
  • Form set – Init
  • Form set – Activate
  • Form – Activate
  • Object – When
  • Form – GotFocus
  • Object – GotFocus
  • Form – QueryUnload
  • Form – Destroy
  • Object – Destroy
  • Form – Unload
  • Form set – Unload
  • Data environment – AfterCloseTables
  • Data environment – Destroy
  • Data environment cursor(s) – Destroy

Load () – перше в послідовності подій об'єкта форма. У цій події ні
один елемент лежить на формі ще не народився і там безглуздо поміщати код
зразок this.text1.value = 'я'. Ця подія рекомендується використовувати для
виконання налаштувань середовища оточення. Особливо це актуально при використанні
приватних сесій даних (це питання розглянемо нижче). Також, тут має сенс
здійснити відкриття таблиць і баз даних, не включаються в об'єкт Data
environment
.

RETURN .F. у події Load() скасовує подальшу завантаження форми.
Якщо форма має private data session всі відкриті таблиці та отримані
курсори закриваються.

Init () – подія при створенні форми. Слід врахувати, що елементи управління,
поміщені на форму, створюються раніше форми, Тобто подія Init ()
елементів відбувається раніше, і тому в події Init() форми вже можна
звертатися до елементів керування форми. Включивши оператор LPARAMETERS в
подія форми, можна здійснити можливість передачі в неї параметрів. Варто
помітити, що видимість цих змінних-параметрів далі події Init () не
поширюється. Тому в разі необхідності варто присвоїти значення
параметрів створеним вами властивостями форми
. Наведемо приклад достатньо
типової помилки, змінні передані в Init () використовуються у виразі для
фільтра на яку або таблицю, що бере участь в роботі форми. Природно, після
спрацьовування події змінних вже немає, і фільтр ставати не
працездатним, тому що його значення обчислюється в момент переміщення по
записів. Якщо необхідно, створення і відповідно запуск форми
можна припинити, виконавши команду RETURN .F. Це зручно, наприклад, для
організації допуску до форм різним користувачам або перевірки вірності умов
запуску форми, без правильності яких, далі форма не зможе вірно
функціонувати.

Activate () – активування форми діями користувача, таким як клацання
мишею, або ж коли викликається метод SHOW() форми. Ця подія при
роботі форми може спрацьовувати багато разів, і іноді код, поміщений в нього, може
доставити різні проблеми. Скажімо, там буде написано який або sql
select

Виконали з форми друк звіту, повернулися в форму, подія знову
відпрацювало, і явно завадило роботі елементів форми, скажімо грід, чиїм
джерелом може бути курсор sql select. Рекомендуємо, якщо немає
можливості приміщення коду в цю подію, перевіряти необхідність повторного
запуску коду в ньому, скажімо, таким чином –

  If not this.old
This.DoSomething
This.old=.t.
endif

Не менш підступним може бути і елементарний код, поміщений в антипода
згаданої події – DEACTIVATE – Яке теж може багаторазово
спрацювати. Куди зміщується фокус з форми-в тулбар, перегляд звіту чи до іншого
місце, у цій події невідомо. Ось у звіті несподівано стає видно одна
запис замість кількох, а все тому, що в зазначеному подію написали всього
один рядок – SELECT MyTable. Особливо кишать такими проблемами сторінкові
форми, з кодами у вказаних подіях на сторінках: хотіли вказати аліас при
зміну сторінки, коли користувач залишається на формі, а він до звіту пішов, і
вибив у нього табуретку з-під нього цим кодом.

GotFocus () – отримання фокусу

Далі форма працює, і на ній можуть спрацьовувати найрізноманітніші події, як
то: натиснення клавіш, оновлення змісту, перемальовування та інші. Поки опустимо
опис цих подій. При розвантаженні форми форми відбуваються інші події

QueryUnload () – це подія відбувається при виконанні команд CLEAR
WINDOWS, RELEASE WINDOWS або QUIT
, а також при натисканні на хрестик вікна
форми. Варто зазначити, що ця подія не відбувається
при
виконанні методу RELEASE() форми. Для того щоб запобігти закриттю
форми виходячи з необхідних розробнику умов, досить виконати команду
NODEFAULT у цій події.

Destroy () – відбувається при знищенні об'єкта

Unload () – це останнє з подія в послідовності перед знищенням
форми, відбувається після звільнення всіх об'єктів включених у форму. Всі
елементи керування, включені в форму, у цій події форми знищені і
недоступні
.

При використанні Default data session у формі саме у цій події
варто закрити таблиці, відкриті з використанням команди USE , А також
отримані курсори.

Якщо форма модальна, використовуючи команду RETURN можна повернути значення
змінної з форми <

  DO FORM MyForm TO VarName

4. Сесії даних


Тим, хто знайомий з програмуванням в процедурних мовах (таких як FoxPro
2.6), відомо, яких зусиль коштувало створення форм з моделюванням незалежних
один від одного сесій. У VFP все це легко вирішується за допомогою private data
session
(Приватних сесій даних). Приватні сесії дозволяють відкривати
таблиці, уявлення, індексні файли, створювати зв'язки, робити всілякі
налаштування в оточенні, абсолютно не піклуючись про те, що в якійсь з іншої
форм аналогічні маніпуляції виконуються з цими ж таблицями. Кожна приватна
сесія абсолютно не залежна в цьому плані від інших. Приватна сесія
подібна оточення даних на одній окремій машині. Тому, якщо розробник
збирається створювати додаток з багатодокументним інтерфейсом, слід взяти за
правило будувати форми на основі приватних сесій даних. Дійсно, в одній
формі можуть брати участь кілька таблиць, пов'язаними різними реляціями, в
інший щось подібне звіту – частина цих же таблиць без реляцій, в третій – вони
ж, але з іншого реляцією. Якщо використовувати загальну сесію, то потрібно або все
час перебудовувати реляції, міняти запис, або давати одним і тим же таблиць
в різних формах різні назви.

Дійсно, у формі накладних можемо перебувати на 30-тій записи
накладних, у звіті оборотна відомість – сканувати записи, а довідники
взагалі знаходитися на різних записах. Якщо відкрито одночасно 5-6 різних форм,
то з назвами аліасів буде повний хаос. При приватній сесії форми не бачать
оточення один одного, одні і ті ж таблиці можна відкрити за одним і тим же
ім'ям, зв'язати їх різними реляціями, перебувати на різних записах одних і тих
же таблиць. Слід звернути увагу на те, що за замовчуванням у формі
встановлена ​​Default data session (1)
– Загальна сесія даних, що часто
збиває початківців розробників з пантелику і змушує їх вдаватися до витонченими
способам програмування MDI форм і багатокористувацьких додатків. Цього
помилкового шляху легко уникнути, встановивши в базовому класі форми Private data
session (2)
. Однак не варто забувати про те, що приватні сесії
даних вимагають додаткових налаштувань середовища, тому як настройки, вироблені
скажімо в головному модулі програми діють лише в загальній сесії даних
(Default data session). Тобто в цьому типі (Private data session)
сесії ігноруються загальні налаштування програми, але їх необхідно виконати
повторно, а саме явно вказати необхідні вам параметри з перерахованих:

SET ANSI
SET AUTOSAVE
SET BLOCKSIZE
SET CARRY
SET CENTURY
SET COLLATE
SET CONFIRM
SET CURRENCY
SET DATABASE
SET DATE
SET DECIMALS
SET DELETED
SET DELIMITERS
SET EXACT
SET EXCLUSIVE
SET FIELDS
SET FIXED
SET HOURS
SET LOCK
SET MARK TO
SET MEMOWIDTH
SET MULTILOCKS
SET NEAR
SET NULL
SET POINT
SET REPROCESS
SET SAFETY
SET SECONDS
SET SEPARATOR
SET SYSFORMATS
SET TALK
SET UNIQUE

Особливо зверніть увагу на налаштування виділені кольором – Вони найчастіше стають причиною розбитих
лобів початківців розробників.

Зважаючи на вищесказане, варто організувати в базовому класі форми якийсь метод,
назвемо його SetSession()в якому і виробляти відповідні
налаштування середовища оточення. Викликати цей метод з події Load() форми.
Якщо метод перевизначається в конкретній формі, використовуйте команду
DODEFAULT(), Щоб виконати метод батька – базового класу форми, в
якому виконуються настройки. Для перемикання між сесіями даних
використовується команда SET DATASESSION. Але користуватися їй рекомендується
тільки на етапі розробки програми для налагодження форм, тому, що деякі
елементи поводяться непередбачувано і дуже болісно реагують на зміну сесії
даних в момент виконання програми, а при зміні програмної сесій деякі
елементи керування просто втрачають свої джерела даних. Приклад, до combobox
підключений джерело даних як аліаса таблиці або її полів. При зміні
сесії це аліас може виявитися тимчасово невидимим, і виникне помилка- can
not access selected tables
. Потрібно відзначити, що послідовність виклику
таких установок може виявитися важливою. Скажімо, в LOAD форми виконується
sql select. Якщо спочатку немає SET TALK OFF, То форма починає
розповідати про свою роботу з виконання запиту, при цьому може псується і
зображення форми. Якщо ви забули про SET DELETED ON, То з подивом
можете виявити в такій формі вже стерті раніше запису. Якщо забули про SET
DECIMAL
, То при розрахунку сум можете втратити точність.

Однією з особливостей форм з private data session є здатність
закривати таблиці з оточення (Data Environment), Таблиць, відкритих при
допомоги команд USE (Тобто так би мовити "вручну") та створених під час
виконання програми курсорів. Це дуже зручно – якщо в процесі відкриття форми
з'явилися службові курсори або ж при її роботі, то піклуватися про їх закриття
не потрібно, вони закриються автоматично.

Прочитавши це, природно виникає питання – а яким же тоді чином форми
можуть обмінюватися даними між собою? Для таких справ передбачений принцип
дочірніх форм. Використовувати його можна двояко. У першому випадку батьківська
(Немодальному) форма з приватною сесією запускає дочірню модальну із загальною
сесією. Такий спосіб хороший для використання при створенні довідників.
Наприклад, запущена дочірня модальна форма набуває ту ж сесію, що і
батьківська і всі дані в дочірній формі їй легко доступні. Сесії, крім
номера, мають найменування, після умовчання збігається з ім'ям запущеної форми.
Так ось при такому підході, сесія спочатку має ім'я батьківської форми, після
запуску дочірньої воно змінюється на ім'я дочірньої форми. Після закриття ж дочірньої
форми ім'я сесії стає невизначеним – Unknown. Хоча
розробники і попереджаються про те, що при закритті дочірньої форми ім'я
сесії втрачається, це не заважає з успіхом використовувати такий підхід при створенні
додатків. Зроблено це все з благою метою. Якщо ви з форм з приватною сесією
викликаєте діалогові форми приміром з питанням про видалення запису, або форму
для запуску звітів, то природно в них бачите ті ж самі таблиці на тих же
записах, що були і в що викликала їх формі з приватної сесією. Тому радимо
уникати відкриття в оточення таких похідних форм таблиць, які вже відкриті
у формі з приватної сесією. Також і в звітах не слід в таких випадках класти
ці таблиці в оточення. Інакше при виклику звіту замість запису видимої на формі,
побачимо перший запис цієї ж таблиці.

Другий спосіб полягає в тому, що дочірня форма є немодальному з
приватній сесією даних. Для запуску таким способом використовується команда DO
FORM … NAME … LINKED
. Використовуйте новостворене властивість форми, скажімо,
назвавши його oChildForm. Виконавши команду з методу батьківської форми:

  DO FORM  NAME ThisForm.oChildForm LINKED

Отримаємо посилання в батьківській формі на дочірню через властивість
oChildForm і вільно можна таким чином звернутися з батьківської
форми до методів і властивостей дочірньою. Крім того, при закритті батьківського
форми буде знищена і дочірня бо вона асоціюється з властивістю
батьківської форми (про що говорилося раніше). Звичайно, не варто забувати про
посиланнях і незавершених методах, тобто при закритті батьківської форми для повної
впевненості виконати:

  ThisForm.oChildForm=.NULL.

5. Модальність і немодальному


Більшість форм у додатку зазвичай немодальному. Але модальні форми теж
мають право на життя. З'являтися їм звичайно ж коштує в потрібному місці і в потрібний
час – там де необхідно перервати виконання програми для виконання
обов'язкових операцій або отримання необхідних даних. Відмінність модальної форми
від не модальної в тому, що при запуску модальної форми програма зупиняється
на рядку DO FORM і чекає до тих пір поки форма не буде закрита,
немодальному ж форма не викликає такої затримки і код продовжує здійсняться
після її запуску. Модальна форма також використовується для повернення якого або
значення з форми:

  DO FORM MyFormName TO MyVariable

Модальність форми визначається властивістю WindowType. Але ця властивість
доступно для зміни тільки на етапі розробки форми. Змінити модальність
запущеної форми при необхідності можна, вдавшись до такої операції:

допустимо форма MyFormName створена як немодальному форма в дизайнера і
запускається таким чином

  PUBLIC oForm
DO FORM MyFormName NAME oForm NOSHOW

тобто форма запущена, але прихована, потім виникає необхідність відобразити її,
причому зробити її модальної:

  oForm.Show(1)

форма відобразиться і прийме статус модальної.

6. Передача параметрів між формами і методами.


Поряд з тим, що деякі дані у формах можуть зберігатися у вигляді властивостей
форми, можливо передавати їх в викликаються методи і як параметри. Цей спосіб
передачі видається більш гнучким при виклику методів однієї форми з іншої
форми. Але цей спосіб загрожує тим, що передані дані ізолюються від інших
методів форми, тобто передані таким чином дані доступні тільки в
викликає і викликається методах форм. Завжди існує ймовірність того, що
дані, які використовуються у двох методах різних форм, можуть знадобитися і в
третьому. Якщо така ситуація не виключена, варто привласнити їх властивостями форми. І
перш ніж написати LPARAMETERS в методі форми, подумайте, наскільки
імовірна така ситуація. Пересилання даних між методами у вигляді параметрів
швидше "ситуаційна" техніка, багато в чому залежить від конкретного випадку, а не
для повсюдного використання. Тому як в об'єктно-орієнтованому
програмуванні (на відміну від процедурного) методи і властивості невіддільні від
об'єкта
(принцип інкапсуляції) І для об'єкта немає великої різниці
працювати йому з перемінними пам'яті або ж зі своїми власними властивостями,
які так чи інакше теж зберігаються в пам'яті.

7. Делегування методів.


Програмуючи в об'єктно-орієнтованої мови, яким є VFP, повинно
розуміти, що набагато легше розподілити виконання деякої задачі між
безліччю методів, ніж виконувати купу умов і перевірок в одному місці,
щоб якомога ширше охопити всілякі варіанти розвитку подій. Приміром,
якщо в коді часто використані конструкції IF-ENDIF, CASE-ENDCASE
і він перевантажений цими перевірками – можна розділити його на більш дрібні ділянки і
винести їх виконання в окремі методи; якщо код методу батька часто
перевизначається в спадкоємця, варто подумати про розширення його функціональності
в батьку і, якщо в метод передається дуже велика кількість параметрів – це
свідчить про занадто вузькою його спрямованості, можливо, що необхідно
виключити його з батьків і перенести в методи спадкоємця. Підхід, при якому
вся функціональність форми перекладається на декілька елементів форми,
часто не правильний. Потрібно чітко уявляти, що форма призначена для
того, щоб відобразити інформацію і якимось способом обробити її. Зовсім не
обов'язково в методі Click() який-небудь кнопки писати кілька сторінок
коду з виконання деякої обробки представлених на формі даних.
Необхідно структурувати їх і розділити задачу на кілька етапів. Потім
представити ці етапи у вигляді методів. По-перше, це підвищить читабельність,
коду, а по друге полегшить спадкування і перевизначення цих методів.
Делегування методів – це інтерпретування наполеонівського принципу "розділяй
і володарюй "в об'єктно-орієнтованому програмуванні;)

Розглянемо приклад для ілюстрації делегування методів:


  • Нехай на формі є грід, джерелом якого є таблиця, відкрита
    з буферизацією 5 (оптимістична буферизація таблиці). У гріді йде правка
    записів таблиці.
  • На формі є кнопка "Записати зміни" Cmd_Save

Заведемо на формі метод Save()

  Select MyTable
Return TableUpdate(.T.)

В Click() кнопки "Записати зміни"

  If !thisform.Save()
Messagebox ('Не вдалося зберегти зміни!', 48, this.caption)
Return .F.
Endif
Return .T.

У події QueryUnload форми

  This.Cmd_Save.Click()

Така побудова методів і подій є типовим прикладом
делегування.

8. Закриття форми


Закриття форми здійснюється методом RELEASE(). Якщо при виконанні
закриття форми потрібно дотримати деякі умови – їх можна прописати в цьому
методі. Перед закриттям форми краще вручну очистити всі посилання на неї в
дочірніх формах, явно присвоївши їм значення .NULL., Інакше форма не буде
закрита. Зазвичай на форму поміщається кнопка в методі Click() якої і
викликається Release() форми. Цю кнопку можна зробити за замовчуванням
асоційованої з Escape, Призначивши її властивість Cancel=.T. Тоді
при натисканні кнопки Escape на клавіатурі виконається метод Click()
елемента управління "кнопка" на формі і форма закриється. Проте є ще одне
"Але" – закриття після натискання "хрестика" на формі. При таких діях
виконується подія QueryUnload форми. Треба зауважити, що метод
Release() і подія QueryUnload взаємонезалежні, тобто при
Release() не відбувається QueryUnload, А подія QueryUnload
закриває форму минаючи Release(), Що досить часто і збиває з пантелику.
Щоб скасувати закриття форми виходячи з умов, достатньо видати
NODEFAULT в цих методах.

9.Горячіе клавіші на формах

Крім стандартного – "мишачого"
маніпулювання об'єктами форми прийнято організовувати так звані "гарячі"
клавіші, при натисканні на які виконуються деякі дії (зазвичай часто
повторювані користувачами під час роботи з програмою). Вважається, що
користувач досконало володіє програмою, якщо він здатний працювати з нею
не вдаючись до допомоги миші. Тому "гарячі" клавіші – неодмінний атрибут
будь-якого грамотно побудованого програми. Натиснення клавіш на клавіатурі
обробляється подією KeyPress. Відразу зауважу, що цією подією НЕ
можуть
бути оброблені будь-які комбінації з клавішею Alt. Не забувайте
про це. Подія KeyPress форми відбувається в наступних випадках:
  • На формі немає елементів управління, або ці елементи управління невидимі або
    недоступні (властивості Visible і Enabled).
  • Коли елемент не може обробити натиснення якоїсь клавіші
  • Коли властивість KeyPreview форми встановлено ст. T.

    В останньому випадку саме форма спочатку обробляє подія KeyPress,
    і тільки потім виконується подія KeyPress елемента управління,
    знаходиться у фокусі на формі. Це дуже зручно, оскільки дозволяє помістити
    код обробки гарячих клавіш в одному єдиному місці, незалежно від того, де
    знаходиться фокус вводу. Інакше б довелося писати код обробки буквально в кожному
    елементі форми. Іншими словами, якщо ви хочете обробити деякі натискання
    клавіш на формі (саме на формі), Встановіть властивість KeyPreview в
    .T.
    При цьому, щоб відсікти всіляку реакцію системи на ці натискання, а
    залишити тільки запрограмовану вами, застосуйте команду NODEFAULT в
    самому початку обробки натискань. Якщо ви бажаєте продовжити обробку натискання
    певної комбінації клавіш крім форми і в елементі керування форми (якщо
    він перебуває у фокусі), виконайте DODEFAULT(nKeyCode, nShiftAltCtrl).
    Якщо не вказати останньої команди, то форма може втратити можливість навігації
    між елементами на ній, а при введенні буде вводитися лише один символ. Радимо
    обережніше працювати у цій події з обробкою клавіш введення і табуляція (коди
    13,10), інакше можуть бути проблеми з кодом у подіях VALID і переходом з
    елементом на елемент. Іншими словами, ці клавіші не дуже підходять на роль
    гарячих. Не будуть спіймані натиснення клавіш, які ви визначили до форми в
    командах типу ON KEY LABEL .


    При підготовці статті використано матеріали професійної документації
    по VisualFoxPro

  • Схожі статті:


    Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

    Коментарів поки що немає.

    Ваш отзыв

    Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

    *

    *