Conception de composants FireMonkey

De RAD Studio
Aller à : navigation, rechercher

Remonter à Guide des composants FireMonkey

Cette rubrique décrit comment concevoir des composants en utilisant FireMonkey.

Aperçu des contrôles intégrés sélectionnés

Un examen de quelques contrôles FireMonkey montre l'étendue des possibilités de conception dans FireMonkey.

TPanel : stylage avec les primitives

Le code source pour TPanel est assez court pour être reproduit dans son intégralité ici. Voici l'interface :

  TPanel = class(TStyledControl)
  public
    constructor Create(AOwner: TComponent); override;
  published
    property StyleLookup;
  end;

et maintenant l'implémentation :

constructor TPanel.Create(AOwner: TComponent);
begin
  inherited;
  Width := 120;
  Height := 100;
end;

TPanel sous-classe TStyledControl, la classe de base pour tous les contrôles de niveau utilisateur. TPanel publie la propriété StyleLookup, qui contient le nom du style à rechercher. Le constructeur définit Width et Height, propriétés de TControl. Mais comment ce contrôle effectue-t-il son rendu ?

L'un des concepts clé de FireMonkey est l'utilisation des styles. Le style par défaut pour TPanel sur Windows peut être vu en enregistrant un fichier .style et est approximativement comme suit :

  object TRectangle
    StyleName = 'panelstyle'
    Width = 50
    Height = 50
    HitTest = False
    Fill.Color = $FFffFFff
    Stroke.Color = $FF8e8e8e
  end

TPanel est un rectangle blanc uni avec une bordure grise. (Sur le Mac, le remplissage est un dégradé.)

En tant que contrôle stylé, TStyleControl contient une propriété ResourceLink qui pointe sur un TFmxObject. ResourceLink est un clone d'une ressource de style du contrôle, ayant été trouvée par son nom (spécifié dans la propriété StyleLookup du contrôle pour correspondre avec la propriété StyleName de la ressource), ou définie par défaut. Cet objet lien de ressource est aussi inséré en tant que premier enfant du contrôle, quand le contrôle est d'abord chargé ou quand sa propriété StyleLookup est changée. Ceci est effectué dans TStyledControl.ApplyStyleLookup.

Ainsi quand, comme un TControl, le contrôle se dessine lui-même, il dessine ses enfants. Le premier enfant correspond au contrôle lui-même, et les autres enfants "réels" (le cas échéant) sont ensuite dessinés.

En tant que contrôle primitif, TRectangle se dessine lui-même dans sa méthode Paint en appelant FillRect et DrawRect sur le canevas.

TCalloutPanel : contrats de style

TCalloutPanel étend TPanel avec des propriétés pour un élément call-out visuel supplémentaire. Le style par défaut pour TCalloutPanel est virtuellement identique à celui pour TPanel, approximativement :

  object TCalloutRectangle
    StyleName = 'calloutpanelstyle'
    Width = 50
    Height = 50
    HitTest = False
    Fill.Color = $FFffFFff
    Stroke.Color = $FF8e8e8e
  end

Au lieu d'un TRectangle, le style de niveau supérieur est un TCalloutRectangle, c'est-à-dire un rectangle avec une pointe triangulaire sur un côté. La primitive a exactement les mêmes propriétés supplémentaires pour le call-out que le contrôle stylé, qu'il utilise pour dessiner ce triangle. Le mappage est effectué par la méthode ApplyStyle :

procedure TCalloutPanel.ApplyStyle;
var
  Back: TFmxObject;
begin
  inherited;
  Back := FindStyleResource('Background');
  if (Back = nil) and (ResourceLink is TCalloutRectangle) then
    Back := ResourceLink;
  if (Back <> nil) and (Back is TCalloutRectangle) then
  begin
    TCalloutRectangle(Back).CalloutWidth := FCalloutWidth;
    TCalloutRectangle(Back).CalloutLength := FCalloutLength;
    TCalloutRectangle(Back).CalloutPosition := FCalloutPosition;
    TCalloutRectangle(Back).CalloutOffset := FCalloutOffset;
  end;
end;

ApplyStyle est appelée par ApplyStyleLookup dès que l'objet lien de ressource est en place, et par chacun des accesseurs en écriture des propriétés supplémentaires. Pour TCalloutPanel, ApplyStyle s'attend à ce que :

  • l'objet racine est un TCalloutRectangle, ce qui est vrai pour le style par défaut ; ou
  • quelque part dans l'arborescence des composants relatifs au style, se trouve un objet TCalloutRectangle ayant le nom de style "Background".

Si l'objet approprié est introuvable, TCalloutPanel ne fonctionne pas : les propriétés supplémentaires qu'il déclare n'ont pas d'effet.

C'est un exemple d'un contrat de style dans lequel les composants utilisés pour formuler un style pour un contrôle doivent se conformer à certaines attentes. Si vous développez un composant qui nécessite un contrat de style spécifique comme celui-ci, il est alors important que ce contrat soit documenté pour les autres utilisateurs de votre composant afin qu'ils puissent développer des styles corrects.

TCalendar : complexité construite

TCalendar n'a pas de style par défaut. A la place, il se construit lui-même dans son constructeur (qui à l'inverse de TPanel, est trop long pour être inclus ici). Dans les faits, TCalendar crée l'arborescence de composants suivante :

  • TLayout dans la partie supérieure
    • Trois contrôles TButton épinglés à gauche utilisant le style "transparentcirclebuttonstyle", pour...
      • Le mois précédent, avec un triangle pointant sur la gauche dessiné par un TPath
      • Aujourd'hui, avec un cercle dessiné par un TEllipse
      • Le mois suivant, avec un triangle pointant sur la droite dessiné par un TPath
    • TPopupBox pour le mois utilisant le style "labelstyle", rempli par les chaînes des mois de l'année, défini pour remplir la zone client restante non occupée par ces trois boutons et ...
    • TPopupBox pour l'année utilisant le style "labelstyle", rempli par les chaînes des années, des dix années antérieures aux dix années postérieures, épinglé à droite
  • TGridLayout épinglé en haut
    • Sept contrôles TLabel pour les jours de la semaine (Dimanche, Lundi, etc.)
  • TGridLayout le plus à gauche, initialement invisible, dimensionné pour une colonne unique
    • Six contrôles TLabel WeekNumbers pour les numéros de semaine, représentés par la propriété WeekNumbers
  • TListBox avec 7 colonnes épinglées en haut, utilisant le style 'transparentlistboxstyle' et AlternatingRowBackground
    • Quarante-deux contrôles TListBoxItem, se terminant par six lignes pour six semaines

Chaque objet de l'arborescence des composants a sa propriété Stored définie sur False et sa propriété Locked définie sur True. La désactivation de la propriété Stored empêche la mise en flux de l'objet dans le fichier .fmx par le Concepteur de fiches. Si la propriété Stored n'est pas désactivée, les sous-composants seront créés de façon redondante lors du chargement. L'activation de la propriété Locked change la façon dont le test de résultats fonctionne et se déclenche, afin que le sous-composant fasse partie du plus grand ensemble.

Dans TCalendar, la position relative des composants est codée en dur, mais leur apparence est presque entièrement contrôlée par les styles. Les exceptions sont les deux triangles et le cercle à l'intérieur des trois boutons dans le coin supérieur gauche. Les boutons eux-mêmes sont stylés. Les popups mois et année sur la droite ont leur style par défaut redéfini pour ressembler aux libellés (au lieu d'un bouton) avec le style libellé par défaut. Les jours de la semaine et les numéros de semaine sont des instances de TLabel et ils utilisent ce style libellé automatiquement. La zone de liste multicolonne utilisée pour afficher les jours du mois est stylée. Enfin, les contrôles jour individuel adopteront le style par défaut pour les éléments zone de liste.

Même en l'absence de style par défaut, que se passe-t-il si la propriété Resource d'un TCalendar est définie ? Comme toujours, la ressource de style résultante sera définie comme le premier enfant du contrôle, ce qui entraîne qu'elle est restituée sous forme d'arrière-plan. Ainsi TCalendar dans son ensemble peut être stylé à un certain degré.

Conseils à propos des composants

Pour récapituler, lors de la création de composants FireMonkey :

  • Utilisez des styles FireMonkey ; les développeurs d'applications pourront ainsi changer l'apparence des applications.
  • Encapsulez un dessin direct avec un contrôle primitif ; ce dernier peut être changé ou sous-classé.
  • Les contrats de styles doivent être documentés.
  • Les composants susceptibles de vous intéresser sont facilement trouvés par leur nom de style, définissez donc la propriété StyleName de façon appropriée.
  • Les contrôles complexes peuvent être construits par le code avec des composants stylés.

Voir aussi