Utiliser la VCL et FireMonkey dans des unités utilisées par des projets Windows ou multiplateforme

Il peut arriver que l'on ait besoin d'utiliser des fonctionnalités liées à l'interface graphique lorsqu'on travaille dans des unités qui seront ensuite utilisées depuis différents types de projets.

Par programmation il est assez facile de distinguer un projet VCL d'un projet FireMonkey en revanche ça ne permet pas de conditionner l'utilisation des unités d'un framework ou un autre. Il est donc nécessaire de le faire au niveau de la compilation.

J'ai déjà abordé la question de la compilation conditionnelle pour exploiter les modes DEBUG et RELEASE proposés par défaut dans les projets récents. Voyons maintenant comment faire de même pour distinguer un projet VCL d'un projet FireMonkey et s'en servir dans une unité qui ne sait aps au départ où elle sera utilisée.

La première possibilité est d'utiliser les composants FNC de TMS Software qui permettent de faire la distinction mais on peut aussi se débrouiller tout seul car on n'a pas forcément les mêmes contraintes.

Je vous propose donc une solution toute simple : déclarer une constante au niveau des projets que vous développez et la tester au niveau des unités communes.

Ce projet d'exemple est un simple "Hello World". La différence entre les trois programmes sera la façon d'afficher le message selon quel type de projet est lancé.

Côté unité commune on peut tester si les frameworks gérés sont déclarés en début de source par ce code qui affiche aussi une information sur le framework utilisé

{$IFDEF VCL}
{$MESSAGE 'Application VCL'}
{$ELSE}
{$IFDEF FMX}
{$MESSAGE 'Application FMX'}
{$ELSE}
{$IFDEF CONSOLE}
{$MESSAGE 'Application console'}
{$ELSE}
{$MESSAGE FATAL 'Please define VCL, FMX or CONSOLE in your project.'}
{$ENDIF}
{$ENDIF}
{$ENDIF}

ou celui-ci qui se contente de bloquer la compilation si le framework n'est pas déclaré

{$IF not (Defined(VCL) or Defined(FMX) or Defined(CONSOLE))}
{$MESSAGE FATAL 'Please define VCL, FMX or CONSOLE in your project.'}
{$ENDIF}

On y teste si la constante VCL est déclarée pour faire ce qu'on doit faire dans le cadre des projets VCL.
On y teste si la constante FMX est déclarée pour faire ce qu'on doit faire dans le cadre des projets FMX.
On y teste si la constante CONSOLE est déclarée pour les projets sans interface graphique. Sachant que CONSOLE est déclarée par le {$APPTYPE CONSOLE} généré par l'assistant de création de projet au niveau d'un programme console. Nous n'aurons donc pas à l'ajouter nous-même.

A vous de voir avec quelle version du code de test vous êtes le plus à l'aise. L'important est de planter la compilation si les constantes utiles ne sont pas définies ce qu'on fait en envoyant un message fatal au compilateur. Reportez-vous à la documentation de la directive MESSAGE pour ses autres paramètres.

Pour la suite de l'unité c'est du classique : on conditionne les USES en fonction de nos besoins

{$IF Defined(VCL)}
uses VCL.Dialogs;
{$ELSEIF Defined(FMX)}
uses FMX.Dialogs;
{$ENDIF}

puis on code la procédure d'affichage selon les possibilités du framework utilisé

procedure AfficheMessage(texte: string);
begin
{$IF Defined(VCL) or Defined(FMX)}
  ShowMessage(texte);
{$ELSEIF Defined(CONSOLE)}
  writeln(texte);
{$ENDIF}
end;

Notez que l'on utilise ShowMessage() en VCL comme en FMX mais que son implémentation est tantôt dans VCL.Dialogs, tantôt dans FMX.Dialogs.

Le projet console est très simple : on crée une nouvelle application console et on y utilise l'unité créée. Delphi déclarant la constante CONSOLE de lui-même nous n'avons rien à faire de plus pour que ça fonctionne.

Les projets VCL et FMX utilisant cette unité sont les mêmes : une fiche, un bouton et un appel de la procédure stockée dans l'unité lors du clic sur ce bouton. Faites le test.

Vous devriez avoir cette erreur de compilation :

[dcc32 Erreur fatale] CommonUnit.pas(14): F1054 Please define VCL, FMX or CONSOLE in your project.

Pour que la compilation passe il faut se rendre sur Projet / Options / Construction / Compilateur Delphi (ou son équivalent selon la version de Delphi utilisée) puis idéalement choisir la cible "Toutes les configurations" et saisir le nom du framework (ou ce que vous voulez tester) dans la rubrique "Définitions conditionnelles".

Il ne reste plus qu'à enregistrer ces paramètres et recompiler votre projet pour qu'il fonctionne.

Comme toujours vous retrouverez les sources des exemples sur GitHub. N'hésitez pas à me poser vos questions ou me donner vos cas d'utilisations, ça peut toujours m'inspirer pour de futurs articles, présentations ou vidéo conférences.


A lire aussi

Webinaire du 5 novembre 2019 : déploiement et débogage à distance (06/11/2019)
Utiliser la VCL et FireMonkey dans des unités utilisées par des projets Windows ou multiplateforme (26/10/2019)
Les patchs à installer sur la version Rio 10.3.2 de Delphi, C++ Builder et RAD Studio (30/09/2019)
Les combinaisons de touches et raccourcis clavier utiles dans l'EDI de Delphi (29/05/2019)
Webinaire du 22 février 2019 : créer des composants visuels sans faire de composant (28/04/2019)
Webinaire du 10 décembre 2018 : découvrez les nouveautés de Delphi 10.3 Rio (20/12/2018)
Le nouvel IDE de Delphi se dévoile peu à peu pour la version 10.3 Rio (10/11/2018)
Les patchs à installer sur la version Tokyo 10.2.3 de Delphi, C++ Builder et RAD Studio (17/09/2018)
Faire attention aux fichiers ouverts lorsqu'on modifie un projet copié d'ailleurs (04/02/2018)
Utiliser les directives de compilations pour ne pas perdre ses données de production en développant ! (21/07/2017)
Contourner l'erreur "ld: warning: unknown dwarf DW_FORM_strp (offset=0xFFFFFF99) is too big in XXX.a(raw.o)" (28/06/2017)
Comment installer Delphi pour que tout fonctionne correctement ? (20/11/2015)

Membre du programme MVP.
Membre du programme MVP