1. Deux formulaires
Nous allons créer une fenêtre pop-up avec Form1 (formulaire principal) et Form2 (fenêtre secondaire)
1. Étapes de réalisation
- Créez un nouveau projet, glissez un Button1 sur Form1, définissez
Caption = Open Form2et générez l’événementOnClick(double-cliquez directement sur le bouton dans le concepteur pour créer rapidement l’événement de clic) ; - Utilisez le menu supérieur
File → New Formpour créer Form2 ; - Ajoutez un Button1 sur Form2, attribuez
Caption = Closeet créez son événementOnClick; - Raccourcis pour naviguer entre formulaires :
Shift+F12ouvrir la liste des formulaires /F12basculer entre vue conception et code ; - Référencer Unit2 dans Unit1 : ajoutez
Unit2dans la sectioninterface uses.
Unit1 (formulaire principal)
Deux points essentiels à respecter : Unit2; // Import de Unit2
Le second point se trouve dans la procédure de clic : ouvrir Form2 en mode modal avec Form2.ShowModal; // Affichage modal de Form2
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Unit2; // Import 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; // Affichage modal de Form2
end;
end.
Unit2 (formulaire secondaire)
Ajouter le second formulaire au projet

Après l’ajout, un nouvel onglet apparaît dans l’éditeur de code
Un onglet contient le code du formulaire principal, l’autre le code backend de Form2


Pour modifier Form2, sélectionnez Unit2 et appuyez sur F12 pour ouvrir sa fenêtre de conception

Ajoutez un bouton, définissez son libellé sur Close et implémentez la fermeture comme vu dans les leçons précédentes. Vous pouvez réaliser cette étape vous-même.
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; // Fermer le Form2 actuel
end;
end.

2. Différences clés entre Show et ShowModal (exemple comparatif)
Modification de l’interface
Ajoutez deux boutons sur Form1 :
- btnShow : Caption = Show
- btnShowModal : Caption = ShowModal

// Non-modal avec Show
procedure TForm1.btnShowClick(Sender: TObject);
begin
Form2.Show;
ShowMessage('Form2 est ouvert, le formulaire principal reste utilisable');
end;
// Modal avec ShowModal
procedure TForm1.btnShowModalClick(Sender: TObject);
begin
Form2.ShowModal;
ShowMessage('Ce message n’apparaît qu’après avoir fermé Form2');
end;Langage du code : JavaScript (javascript)
Explication des écarts
Show(non-modal)
- L’exécution du code se poursuit immédiatement après l’ouverture du formulaire secondaire ;
- Le formulaire principal est déplaçable et ses autres boutons cliquables ;
- Équivaut à
Form2.Visible := True;et place automatiquement la fenêtre au premier plan.
ShowModal(fenêtre modale)
- L’exécution du code est suspendue tant que le formulaire secondaire n’est pas fermé ;
- Le formulaire principal est verrouillé, impossible d’interagir avec lui ;
- C’est une fonction qui renvoie une valeur
ModalResultpour savoir comment la fenêtre a été fermée.
En résumé : une fenêtre modale vous oblige à fermer la fenêtre secondaire avant de manipuler le formulaire principal ; une fenêtre non-modal permet d’utiliser les deux en même temps.
3. Appels croisés entre formulaires : corriger l’erreur de référence circulaire
Besoin : Form1 ouvre Form2, Form2 ouvre Form1
Si vous ajoutez des références mutuelles dans interface uses, une erreur de dépendance circulaire survient. Solution : placer les références dans la section 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; // Placer la référence ici
{$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éférences croisées dans l’implémentation
{$R *.lfm}
procedure TForm2.Button1Click(Sender:TObject);
begin
Form1.Show;
end;
end.
4. Passer des valeurs entre formulaires (exemple avec variable membre publique)
Fonctionnalité : incrémenter un compteur à chaque ouverture du formulaire secondaire depuis le principal ; le second formulaire affiche le nombre d’ouvertures
Définir une variable entière publique dans Unit2
type
TForm2 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
Count: Integer; // Variable publique accessible depuis Unit1
end;
Incrémenter le compteur au clic sur le bouton de Unit1
procedure TForm1.Button1Click(Sender: TObject);
begin
Inc(Form2.Count); // Augmenter le compteur de 1
Form2.ShowModal;
end;Langage du code : JavaScript (javascript)
Afficher le nombre d’ouvertures dans Unit2
procedure TForm2.Button1Click(Sender: TObject);
begin
ShowMessage('Ce formulaire a été ouvert '+IntToStr(Count)+' fois');
end;Langage du code : JavaScript (javascript)
Bonne pratique de développement : limiter l’usage des variables globales ou publiques ; préférez les propriétés Property pour transmettre des valeurs.
5. Créer des formulaires dynamiquement
Sans recourir aux variables globales de formulaire générées automatiquement par le projet
Méthode 1 : instanciation dynamique d’un Form2 déjà conçu
- Ouvrez le fichier
Project.lpret supprimez la ligneApplication.CreateForm(TForm2, Form2); - Code du bouton sur Form1 :
procedure TForm1.Button1Click(Sender: TObject);
var
frm2: TForm2;
begin
frm2 := TForm2.Create(nil); // Création manuelle de l’instance
frm2.ShowModal;
FreeAndNil(frm2); // Libérer la mémoire pour éviter les fuites
end;Langage du code : JavaScript (javascript)
Méthode 2 : formulaire entièrement généré par code (sans conception préalable)
Un clic sur le bouton génère une nouvelle fenêtre complète avec un bouton de fermeture intégré
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); // Gestionnaire de clic pour bouton dynamique
public
end;
var Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.DynamicBtnClick(Sender: TObject);
begin
ShowMessage('Fermeture du formulaire dynamique en cours');
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 := 'Formulaire généré dynamiquement';
// Créer un bouton propriétaire de MyForm, détruit automatiquement à la fermeture
MyBtn := TButton.Create(MyForm);
MyBtn.SetBounds(10,10,200,30);
MyBtn.Caption := 'Fermer la fenêtre';
MyBtn.Parent := MyForm;
MyBtn.OnClick := @DynamicBtnClick;
MyForm.ShowModal;
FreeAndNil(MyForm);
end;
end.
Boîte de dialogue « Choose Debug Information format » s’affiche



Il suffit de configurer le format de débogage pour résoudre ce problème.
Gestion de plusieurs formulaires sous Lazarus