Programmer ses applications FireMonkey avec style et tenir compte des paramètres du système

Comme on a pu le constater lors de tests en live coding sur Twitch, l'utilisation des styles pose parfois problème quand on n'a pas l'habitude de jouer avec eux. Et bien entendu, comme je ne m'en sers jamais, c'est toujours un "plaisir" de redécouvrir la chose quand le besoin se fait sentir.

Là, c'était pour détecter les styles clair / sombre de Windows 10 et 11 afin de mettre en place deux styles de couleurs différents dans un programme destiné à s'exécuter sur Windows, Mac et Linux.

Ca a donc été l'occasion de se replonger sur le sujet et revoir les bases pour rédiger cet article.

Alors déjà, concernant les styles dans les projets Delphi, il y a deux systèmes différents selon qu'on est en VCL ou en FireMonkey. Aujourd'hui c'est FMX qui nous intéresse. Pour la VCL j'ai déjà abordé le sujet.

Rappels sur l'utilisation des styles en FireMonkey

En FireMonkey tout se passe entre la classe TStyleManager et les composants TStyleBook facultatifs.

TStyleManager gère le style actuel par défaut de l'application. On le change en appelant sa méthode SetStyle(). Il est appliqué aux fenêtres dont la propriété StyleBook est vide (nil) et les nouvelles fiches ou boites de dialogue compatibles avec les styles FMX.

TStyleBook est un conteneur de styles ayant différentes versions pour les plateformes (= systèmes d'exploitation) qu'on y charge. De nombreux styles sont fournis avec RAD Studio & Delphi. D'autres sont ajoutés régulièrement dans GetIt et on en trouve aussi chez différents revendeurs quand on ne veut pas créer le sien et qu'on ne veut pas des styles par défaut.

TStyleBook a une propriété UseStyleManager qui n'a d'impact qu'au chargement du composant. Changer sa valeur en cours d'utilisation n'a aucun impact nulle part.

Si on veut changer le style d'une fiche on peut modifier sa propriété StyleBook. Par défaut les fiches prennent le style référencé au niveau du TStyleManager lors de leur création si aucun StyleBook ne leur est affecté.

Sachant ça on doit pouvoir manipuler les styles d'un projet comme dans l'exemple ci-joint.

procedure TEcranPrincipal.btnPartoutClick(Sender: TObject);
var
  style: TStyleBook;
begin
  Style1Ou2 := 3 - Style1Ou2;
  case Style1Ou2 of
    1:
      style := StyleBook1;
    2:
      style := StyleBook2;
  end;
  tstylemanager.SetStyle(style.style.Clone(Self));
  setstylebook(style);
end;

Notez que pour activer le style sur le TStyleManager je clone les données de style des TStyleBook. La raison en est simple : le TStyleManager libère les données qu'on lui a fournies si on change le style, du coup le passage d'un TStyleBook sans clonage à l'autre supprimait son contenu.
Petite subtilité, mais importante à avoir en tête.

Détecter le mode clair ou sombre du système d'exploitation

FireMonkey nous donne accès à ce genre d'informations à travers des services de plateforme principalement disponibles dans l'unité FMX.Platform

C'est aussi le cas ici avec IFMXSystemAppearanceService.

Lorsque ce service de plateforme est implémenté on y trouve la propriété ThemeKind qui peut prendre l'une des 3 valeurs suivantes : TThemeKind.Unspecified, TThemeKind.Light ou TThemeKind.Dark

Malheureusement, pour le moment (Delphi 11.1 Alexandria), ce service n'est implémenté que pour iOS, Mac et Android. Pas encore pour Windows.

Du coup, en attendant son implémentation par rapport à Windows, on doit utiliser le même fonctionnement manuel que pour les projets VCL comme décrit par Ian Barker dans cet article et plus précisément dans ce code source.

Notre programme devra donc :

- tester si le service de plateforme est implémenté et l'utiliser si c'est le cas

- si ce n'est pas le cas, quand on est sur une plateforme Windows, regarder la base de registres et voir si la clé Software\Microsoft\Windows\CurrentVersion\Themes\Personalize\AppsUseLightTheme est à 0 (thème sombre) ou 1 (thème clair).

- afficher le style choisi (soit par défaut, soit par l'utilisateur si on lui laisse le choix (recommandé), soit à partir de la configuration du système d'exploitation)

procedure TForm1.SetDefautLightDarkStyle;
var
  svc: IFMXSystemAppearanceService;
begin
  if TPlatformServices.Current.SupportsPlatformService
    (IFMXSystemAppearanceService, svc) then
    case svc.ThemeKind of
      tsystemthemekind.Light:
        ThemeClair;
      tsystemthemekind.dark:
        ThemeSombre;
    end
{$IFDEF MSWINDOWS}
  else if WindowsDarkModeIsEnabled then
    ThemeSombre
{$ENDIF}
  else
    ThemeClair;
end;

Voyez l'exemple complet ci-joint pour le reste du code.

Par défaut FireMonkey fait la détection du thème lors du démarrage d'un programme pour les plateformes sur lesquelles il gère la détection et embarque plusieurs thèmes. On peut activer manuellement l'un des thèmes qu'il propose.

Sur iOS on peut aussi ajouter une clé au fichier Info.plist afin de forcer le thème sombre ou clair par défaut sans tenir compte de la valeur système. C'est la clé UIUserInterfaceStyle qui peut se saisir directement dans les informations du projet au niveau des infos de version. Comme c'est le système d'exploitation qui en tient compte au lancement de l'application, c'est pris aussi en charge par FMX et donc votre projet lors de sa détection du thème actuel.

Certaines informations n'ont pas été affichées. Vous devez vous connecter pour y accéder.

Connexion Inscription


Fichiers associés

Certaines informations n'ont pas été affichées. Vous devez vous connecter pour y accéder.

Connexion Inscription


Mug Pascal case in AlexandrieMug Toucan DX dans la baie de Rio