1. Dos formularios
Vamos a implementar una ventana emergente con Form1 (formulario principal) y Form2 (ventana popup)
1. Pasos a seguir
- Crea un proyecto nuevo, arrastra un Button1 sobre Form1, establece
Caption = Open Form2y genera el eventoOnClick(puedes hacer doble clic directamente sobre el botón en el diseñador para crear el evento de clic rápidamente); - Usa el menú superior
File → New Formpara crear Form2; - Coloca un Button1 en Form2, configura
Caption = Closey genera su eventoOnClick; - Atajos para alternar formularios:
Shift+F12abrir lista de formularios /F12alternar vista diseño y código; - Referenciar Unit2 desde Unit1: agrega
Unit2dentro deinterface uses.
Unit1 (Formulario principal)
Hay dos puntos clave que debes tener en cuenta: Unit2; // Importar Unit2
El segundo punto está dentro del procedimiento de clic: abrir la ventana 2 en modo modal con Form2.ShowModal; // Mostrar Form2 de forma modal
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2; // Importar 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; // Mostrar Form2 de forma modal
end;
end.
Unit2 (Formulario secundario)
Cómo agregar el segundo formulario al proyecto

Después de crearlo, aparecerá una pestaña adicional en el editor de código
Una pestaña guarda el código del formulario principal y la otra el código backend de Form2


Para editar Form2, selecciona Unit2 y pulsa F12 para abrir su ventana de diseño

Agrega un botón, cambia su texto a Close e implementa la lógica de cierre tal como vimos en lecciones anteriores. Puedes completarlo por tu cuenta.
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; // Cerrar el Form2 actual
end;
end.

2. Diferencias fundamentales entre Show y ShowModal (ejemplo comparativo)
Modificar la interfaz
Agrega dos botones en Form1:
- btnShow: Caption = Show
- btnShowModal: Caption = ShowModal

// Ventana no modal con Show
procedure TForm1.btnShowClick(Sender: TObject);
begin
Form2.Show;
ShowMessage('Form2 abierto, el formulario principal se puede manipular');
end;
// Ventana modal con ShowModal
procedure TForm1.btnShowModalClick(Sender: TObject);
begin
Form2.ShowModal;
ShowMessage('Este aviso solo aparece después de cerrar Form2');
end;Lenguaje del código: JavaScript (javascript)
Explicación de las diferencias
Show(No modal)
- El código sigue ejecutándose inmediatamente tras abrir el formulario secundario;
- Se puede arrastrar el formulario principal y pulsar otros botones sin restricciones;
- Equivale a
Form2.Visible := True;y coloca la ventana automáticamente en primer plano.
ShowModal(Ventana modal)
- La ejecución del código se detiene hasta que se cierre el formulario secundario;
- El formulario principal queda bloqueado y no se puede usar;
- Es una función que devuelve
ModalResultpara saber cómo se cerró la ventana.
En pocas palabras: con una ventana modal debes cerrar la ventana hija para interactuar con la principal; con una no modal puedes operar ambas ventanas al mismo tiempo.
3. Llamadas mutuas entre formularios: solucionar error de referencia circular
Requerimiento: Form1 abre Form2, Form2 abre Form1
Si te refieres mutuamente en interface uses aparecerá un error de unidades circulares. Solución: mover las referencias a la sección 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; // Coloca aquí la referencia
{$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; // Las referencias mutuas van en implementation
{$R *.lfm}
procedure TForm2.Button1Click(Sender:TObject);
begin
Form1.Show;
end;
end.
4. Pasar valores entre formularios (ejemplo con variable miembro pública)
Funcionalidad: incrementar un contador cada vez que el formulario principal abre el secundario; el formulario secundario puede consultar el número de aperturas
Declarar variable entera pública en Unit2
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
Count: Integer; // Variable pública accesible desde Unit1
end;
Incrementar contador al pulsar el botón de Unit1
procedure TForm1.Button1Click(Sender: TObject);
begin
Inc(Form2.Count); // Aumentar el contador en 1
Form2.ShowModal;
end;Lenguaje del código: JavaScript (javascript)