
Тема: Відображення модальних і немодальних форм. |
Мета. Ознайомити студентів з основними принципами програмування діалогових форм. |
Теоретичний матеріал Відображення модальної форми
Модальна форма виводиться на екран таким чином, що при роботі з нею користувач не одержить доступу до інших частин додатку доти, доки ця форма не буде закрита. Звичайно, модальні форми зв'язані з діалоговими вікнами і використовуються набагато частіше немодальних. Для виклику форми в модальному режимі використовується метод ShowModal(). Приведений нижче код — це приклад створення екземпляра форми TModalForm і виводу її на екран як модальної.
begin //Створення екземпляра форми
ModalForm := TModalForm.Create(Application);
try
if ModalForm.ShowModal = mrOk then //Відображення форми в модальному режимі
{ оператори }; //Виконання деяких дій
finally
ModalForm.Free; //Звільнення об'єкта форми
ModalForm := nil; //Знищення об'єкта форми
end;
end;
Тут показано, як динамічно створити екземпляр об'єкта TModalForm і присвоїти його змінній ModalForm. Варто відмітити, що при створенні об'єкта форми динамічно, необхідно видалити її зі списку доступних форм Auto-Create, розташованого у вкладці Forms діалогового вікна Project Options. (Це вікно виводиться на екран за допомогою команди Project/Options.) У тому випадку, коли екземпляр форми вже створений, вивести її на екран як модальну можна просто за допомогою виклику методу ShowModal(). При цьому весь навколишній текст варто видалити:
begin
if ModalForm.ShowModal = mrOk then // Форма ModalForm уже створена
{ щось виконати } // Виконання деяких дій
end;
Метод ShowModal() повертає значення, присвоєне властивості ModalResult. По замовчуванню це значення дорівнює нулю і відповідає визначеній константі mrNone. Присвоєння властивості ModalResult ненульового значення приводить до негайного закриття форми і поверненню цього значення як результату виконання методу ShowModal().
Властивість ModalResult є і в об'єктів кнопок. Якщо йому заздалегідь присвоїти деяке значення, то при клацанні мишкою на кнопці встановлене значення буде присвоєно властивості ModalResult форми. Це викличе її закриття (якщо встановлене значення не дорівнює mrNone) і повернення у функцію, яка викликала, того значення, яке було присвоєно властивості кнопки.
Значення властивості ModalResult форми можна присвоїти і під час роботи програми:
begin
ModalForm.ModalResult := 100 {Присвоєння значення ModalResult. Це приведе до закриття форми}
end;
-
Константа
Значення
mrNone
0
mrOk
idOk
mrCancel
idCancel
mrAbort
idAbort
mrRetry
idRetry
mrlgnore
idlgnore
mrYes
idYes
mrNo
idNo
mrAll
mrNo+1
У табл. 1 показані визначені значення властивості ModalResult.
Вивід немодальної форми
Немодальна форма відображається за допомогою виклику методу Show(). У випадку відображення форми як немодальної (на відміну від модальних форм) користувач зможе переключатися між нею й іншими формами додатку. Призначення немодальних форм – це надання користувачу можливості одночасно працювати з різними частинами того самого додатку, що представлений різними формами. Приклад динамічного створення і використання немодальної форми:
begin if not Assigned(Modeless) then begin Modeless := TModeless.Create(Application); Modeless.Show end; end |
{Перевірка на наявність немодальної форми Modeless}
// Створення форми // Вивід форми як немодальної // Форма не виводиться – її об'єкт вже існує |
У приведеному коді також показано, яким чином попередити створення декількох екземплярів однієї і тієї ж форми. Адже при роботі немодальної форми користувач може взаємодіяти з іншими частинами додатка, а отже, ніщо не заважає йому знову звернутися до команди меню, що виводить вже виведену форму ТModeless. Дуже важливо коректним чином організувати процеси створення і знищення об'єктів форм.
Ще один немаловажний момент – при закритті немодальної форми (з допомогою команди меню або клацання на кнопці закриття у верхньому правому куті форми) форма автоматично не звільняється. Екземпляр форми залишається в пам'яті до закриття головної форми, тобто фактично до припинення роботи додатку. У попередньому прикладі оператор у фразі then умовного виразу забезпечує створення й вивід форми тільки в тому випадку, якщо вона ще не була створена. У іншому випадку ці дії блокуються, оскільки об'єкт форми вже існує (хоча сама форма вже може бути закрита). Усе це прекрасно, якщо додаток повинний працювати саме в такий спосіб. Однак, якщо ж необхідно звільняти форму всякий раз, коли користувач її закриває, буде потрібно підготувати підпрограму обробки її події OnClоse, параметру Action якого повинне бути привласнене значення caFree. Це вкаже підпрограмам бібліотеки VCL на необхідність звільнити форму при її закритті:
procedure TModeless.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
Action := caFree; // Звільнення екземпляра об'єкта форми при її закритті
end;
Приведений вище приклад вирішує проблему звільнення форми при її закритті. Однак існує ще одна проблема. Розглянемо виконання наступного рядка із приведеного вище приклада відображення немодальної форми:
if not Assigned(Modeless) then begin
Цей оператор перевіряє наявність екземпляра об'єкта класу TModeless по значенню змінної Modeless, яка зсилається на нього. Фактично перевіряється рівність змінної Modeless значенню nil. Хоча значення змінної Modeless при першому виконанні цієї підпрограми дійсно буде дорівнює nil, однак при всіх наступних входах у дану підпрограму після чергового видалення форми TModeless воно вже не буде дорівнює цьому значенню. Справа в тім, що підпрограми бібліотеки VCL автоматично не привласнюють значення nil змінної Modeless при звільненні форми. Тому ця дія повинна виконуватися самою програмою.
На відміну від модальної форми, програма не може прямо установити момент знищення немодальної форми. Отже, не можна знищувати форму в межах тієї підпрограми, що її створює. Користувач може закрити форму в будь-який момент роботи з додатком. Тому присвоєння змінної Modeless значення nil повинне виконуватися самим класом TModeless. Найкращим місцем для виконання подібних дій є підпрограма обробки події OnDestroy класу TModeless:
procedure TModeless.FormDestroy(Sender: TObject);
begin
Modeless := nil; // Скидання значення змінної при знищенні форми
end;
І тепер при кожнім знищенні об'єкта форми змінної Modeless буде привласнюватися значення nil і результати виконання методу Assigned() завжди будуть коректні. Проте не забувайте здійснювати контроль за тим, щоб у кожен момент часу в програмі існувало не більш одного екземпляра класу TModeless, як це зроблено в приведеному раніше прикладі.
Увага
Уникайте наступної помилки під час використання немодальних форм:
begin Form1 := TForm1.Create(Application); Form1.Show(); end;
Подібне рішення може викликати марний розхід пам’яті, оскільки при кожному створенні екземпляра форми перекривається поточне значення вказівника Form1. В результаті неодноразового виконання цього коду Ви отримаєте форми не зв’язані з жодними змінними. Хоча доступ до кожного із створених екземплярів форми може бути здійснений за допомогою списку Screen.Forms, рекомендується уникати подібних рішень. Передача ж в конструктор Create() параметра nil приведе до того, що навіть такий метод доступу до загублених форм буде неможливим.
|
______________________________________________________________________