1. Две формы
Реализуем всплывающее окно: Form1 (основная форма) + Form2 (окно попапа)
1. Пошаговая инструкция
- Создайте новый проект, перетащите кнопку Button1 на Form1, установите
Caption = Open Form2и создайте событиеOnClick(можно быстро создать клик двойным щелчком по кнопке в дизайне формы); - Через верхнее меню
File → New Formсоздайте вторую форму Form2; - Разместите Button1 на Form2, задайте
Caption = Closeи создайте событиеOnClickдля неё; - Горячие клавиши для переключения форм:
Shift+F12открыть список форм /F12переключать вид дизайна и кода; - Подключить Unit2 в Unit1: добавьте строку
Unit2в блокinterface uses.
Unit1 (Основная форма)
Есть два важных момента: Unit2; // Подключение модуля Unit2
Второй момент находится внутри обработчика клика — открыть Form2 как модальное окно командой Form2.ShowModal; // Модальный показ Form2
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2; // Подключаем Unit2
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.ShowModal; // Модальный показ Form2
end;
end.
Unit2 (Дочерняя форма)
Как добавить вторую форму в проект

После добавления в редакторе появится дополнительная вкладка
Одна вкладка содержит код основной формы, другая — код Form2


Чтобы редактировать Form2, выберите вкладку Unit2 и нажмите F12 — откроется дизайнер формы

Добавьте кнопку, установите надпись Close и реализуйте закрытие окна, как показано в предыдущих уроках. Вы можете сделать это самостоятельно.
unit Unit2;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
{ TForm2 }
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form2: TForm2;
implementation
{$R *.lfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
Close; // Закрыть текущую Form2
end;
end.

2. Основные различия Show и ShowModal (сравнительный пример)
Изменение интерфейса
Добавьте две кнопки на Form1:
- btnShow: Caption = Show
- btnShowModal: Caption = ShowModal

// Немодальный вызов Show
procedure TForm1.btnShowClick(Sender: TObject);
begin
Form2.Show;
ShowMessage('Окно Form2 открыто, основная форма доступна для работы');
end;
// Модальный вызов ShowModal
procedure TForm1.btnShowModalClick(Sender: TObject);
begin
Form2.ShowModal;
ShowMessage('Это сообщение появится только после закрытия Form2');
end;Code language: JavaScript (javascript)
Объяснение различий
Show(немодальное окно)
- Код продолжает выполняться сразу после открытия дочерней формы;
- Основную форму можно перетаскивать и нажимать другие кнопки;
- Эквивалентно записи
Form2.Visible := True;, окно автоматически выводится на передний план.
ShowModal(модальное окно)
- Выполнение кода приостанавливается до закрытия дочерней формы;
- Основная форма блокируется, взаимодействие с ней невозможно;
- Это функция, возвращающая значение
ModalResultдля определения способа закрытия окна.
Кратко: модальное окно блокирует работу основной формы до своего закрытия, немодальное позволяет одновременно работать с обеими формами.
3. Взаимный вызов форм: исправление ошибки циклической ссылки
Задача: Form1 открывает Form2, Form2 открывает Form1
Взаимное подключение модулей в блоке interface uses вызовет ошибку циклических зависимостей. Решение: перенести подключения в блок implementation
Unit1
unit Unit1;
interface
uses Forms,StdCtrls;
type
TForm1=class(TForm)
Button1:TButton;
procedure Button1Click(Sender:TObject);
end;
var Form1:TForm1;
implementation
uses Unit2; // Подключение здесь
{$R *.lfm}
procedure TForm1.Button1Click(Sender:TObject);
begin
Form2.Show;
end;
end.
Unit2
unit Unit2;
interface
uses Forms,StdCtrls;
type
TForm2=class(TForm)
Button1:TButton;
procedure Button1Click(Sender:TObject);
end;
var Form2:TForm2;
implementation
uses Unit1; // Взаимные ссылки в блоке реализации
{$R *.lfm}
procedure TForm2.Button1Click(Sender:TObject);
begin
Form1.Show;
end;
end.
4. Передача значений между формами (пример с публичной переменной-членом)
Функционал: при каждом открытии дочерней формы из основной увеличивать счётчик, дочерняя форма показывает общее количество открытий
Объявить публичную целую переменную в Unit2
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
Count: Integer; // Публичная переменная, доступная из Unit1
end;
Увеличить счётчик по клику кнопки в Unit1
procedure TForm1.Button1Click(Sender: TObject);
begin
Inc(Form2.Count); // Увеличить счётчик на единицу
Form2.ShowModal;
end;Code language: JavaScript (javascript)
Вывести количество открытий в сообщении из Unit2
procedure TForm2.Button1Click(Sender: TObject);
begin
ShowMessage('Эта форма открыта '+IntToStr(Count)+' раз');
end;Code language: JavaScript (javascript)
Рекомендация по стилю кода: минимизируйте использование глобальных и публичных переменных, предпочитайте передачу данных через свойства Property.
5. Динамическое создание форм
Без использования автоматически генерируемых глобальных переменных форм проекта
Способ 1: Динамическое создание готовой Form2
- Откройте файл
Project.lprи удалите строкуApplication.CreateForm(TForm2, Form2); - Код кнопки на Form1:
procedure TForm1.Button1Click(Sender: TObject);
var
frm2: TForm2;
begin
frm2 := TForm2.Create(nil); // Ручное создание экземпляра
frm2.ShowModal;
FreeAndNil(frm2); // Освободить память, избежать утечек
end;Code language: JavaScript (javascript)
Способ 2: Полностью генерировать форму кодом (без предварительного дизайна)
По нажатию кнопки создаётся новое окно со встроенной кнопкой закрытия
unit Unit1;
interface
uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
procedure DynamicBtnClick(Sender: TObject); // Обработчик для динамической кнопки
public
end;
var Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.DynamicBtnClick(Sender: TObject);
begin
ShowMessage('Закрываем динамически созданное окно');
TForm(TButton(Sender).Parent).Close;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyForm: TForm;
MyBtn: TButton;
begin
MyForm := TForm.Create(nil);
MyForm.SetBounds(100,100,220,150);
MyForm.Caption := 'Динамически созданная форма';
// Создать кнопку, владелец MyForm — кнопка удалится автоматически при закрытии окна
MyBtn := TButton.Create(MyForm);
MyBtn.SetBounds(10,10,200,30);
MyBtn.Caption := 'Закрыть окно';
MyBtn.Parent := MyForm;
MyBtn.OnClick := @DynamicBtnClick;
MyForm.ShowModal;
FreeAndNil(MyForm);
end;
end.
Появляется окно «Choose Debug Information format»



Достаточно настроить формат отладочной информации, чтобы всё работало корректно.