IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ DelphiConsultez toutes les FAQ

Nombre d'auteurs : 124, nombre de questions : 929, dernière mise à jour : 31 décembre 2023  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).

Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.

L'équipe Delphi de Developpez.com.

SommaireFiremonkey - FMX (10)
précédent sommaire suivant
 

Sous FMX un menu popup prend la main comme une fenêtre modale.
La forme appelante n'a donc pas d'accès direct pour fermer ce menu (en VCL on utilisait ClosePopup).

Pour fermer les popups d'une forme FMXForm1, on utilisera l'objet Screen (variable globale) et les instructions suivantes :

Code : Sélectionner tout
1
2
Screen.PrepareClosePopups(FMXForm1); 
Screen.ClosePopupForms;
L'objet Screen nous permet d'obtenir :
  • Les formes et modules de données créés par l'application.
  • La forme active et le contrôle actif au sein de cette dernière.
  • Le nombre de formes de cette application.
  • Une liste des écrans sur lesquels les formes de l'application peuvent apparaitre ainsi que leurs coordonnées et dimensions.

Mis à jour le 29 juin 2015 SergioMaster

Le style clearingeditstyle d'un TEdit permet d'ajouter un bouton contenant une croix dans la zone de saisie ; ce bouton permet à l'utilisateur d'effacer le texte en cliquant dessus.

Mais jusqu'à la version XE8, si l'on établit la propriété style d'un TEdit à clearingeditstyle (par l'inspecteur d'objets), le bouton apparaît bien dans la zone de saisie mais rien ne se passe lorsque l'utilisateur clique sur ce bouton (le texte n'est pas effacé).

Il y a quand même un moyen pour que cela fonctionne : (sur la fiche en conception) il faut pour cela faire bouton droit sur le TEdit et choisir 'Ajouter un élément' -> TClearEditButton. Cela rajoute le bouton dans la zone de saisie mais cette fois-ci, le clic sur ce bouton fonctionne, le texte est bien effacé.

Mis à jour le 2 juillet 2015 free07

Pour obtenir le nombre de pixels par pouce de l'écran en VCL, nous pouvons utiliser Screen.PixelsPerInch.
Avec FMX, c'est un peu plus complexe, car il faudra utiliser une interface particulière : IFMXDeviceMetricsService.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
function Pixels : integer; 
var D : IFMXDeviceMetricsService; 
    Q : TDeviceDisplayMetrics; 
begin 
result:=96; // valeur par défaut windows 
if TPlatformServices.Current.SupportsPlatformService(IFMXDeviceMetricsService,D) then 
begin 
 Q:=D.GetDisplayMetrics; 
 result:=Q.PixelsPerInch; 
end; 
end;
Il faudra aussi au préalable avoir déclaré dans la liste des uses l'utilisation de l'unité FMX.Platform.

Mis à jour le 18 janvier 2019 SergioMaster

Aller dans l'Inspecteur d'objets, sélectionner la forme principale, puis Propriétés, Position et, dans la liste, choisir OwnerFormCenter. Faire de même pour la forme enfant.

Mis à jour le 22 octobre 2015 Aooka

La version TreeView du framework FMX ne propose pas les mêmes méthodes et propriétés que celui de la VCL.
Il y a trois possibilités pour parcourir l'arbre dépendant de l'objectif souhaité.

Parcourir les éléments de la racine
Pour cela il faut utiliser la propriété Count et la méthode IndexByIndex() du composant
* même les éléments cachés (propriétés visible:=false)
exemple :

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  
procedure TForm1.RacinesVisibles; 
var 
  I: Integer; 
begin 
  Memo1.lines.clear; 
  for I := 0 to Arbre.count - 1 do 
  begin 
    // exemple de traitement 
	// if arbre.ItemByIndex(i).Isselected then 
    Memo1.lines.Add(Arbre.ItemByIndex(I).Text); 
  end; 
end;

Parcourir tous les éléments visibles* de l'arbre
Il faudra utiliser la propriété GlobalCount et la méthode ItemByGlobalIndex() du composant.
* Ici visible indique les éléments qui seront en vue (même ceux avec la propriété visible à false)
exemple :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  
procedure TForm1.ElementsVisibles; 
var 
  I: Integer; 
begin 
  Memo1.lines.clear; 
  for I := 0 to Arbre.GlobalCount - 1 do 
  begin 
    // exemple de traitement  
    // if arbre.ItemByGlobalIndex(i).Isselected then  
    Memo1.lines.Add(Arbre.ItemByGlobalIndex(I).Text); 
  end; 
end;

Parcourir tous les éléments de l'arbre
Pas de secret, il faudra passer par la récursivité et par la connaissance des propriétés des éléments d'un TreeView de type TTreeViewItem.

exemple :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  
procedure TForm1.ArbreEntier; 
var 
  I: Integer; 
//  tous, selections, vue, visibles : Integer; 
  
  procedure getChilds(AnItem: TTreeViewItem); 
  var 
    c: Integer; 
  begin 
//    if AnItem.isExpanded then inc(vus, AnItem.count); 
  
    for c := 0 to AnItem.count - 1 do 
    begin 
//    inc(tous); 
//    if AnItem.ItemByIndex(c).Isselected then inc(selections); 
//    if AnItem.ItemByIndex(c).IsVisible then inc(visibles); 
      Memo1.lines.Add(StringOfChar('-', Pred(AnItem.ItemByIndex(c).Level) * 2) +  // ajoute '--' pour chaque niveau  
        ' ' + AnItem.ItemByIndex(c).Text); 
      if AnItem.ItemByIndex(c).count > 0 then // l'élément a des enfants appel à la procedure récursive 
        getChilds(AnItem.ItemByIndex(c)); 
    end; 
  end; 
  
begin 
  Memo1.lines.clear; 
//  tous := 0; 
//  selections := 0; 
//  vue := 0; 
//  visibles :=0; 
  for I := 0 to Arbre.count - 1 do 
  begin 
//    inc(tous); 
//    inc(vue); // racine toujours visible 
//    if Arbre.ItemByIndex(I).IsSelected then inc(selections); 
//    if Arbre.ItemByIndex(I).IsVisible then inc(visibles); 
    Memo1.lines.Add(Arbre.ItemByIndex(I).Text); 
    if Arbre.ItemByIndex(I).count > 0 then // appel procedure récursive 
      getChilds(Arbre.ItemByIndex(I)) 
  end; 
//  Memo1.lines.Add(Format('Total : %d, en vue : %d, sélectionnés : %d, visibles : %d', 
//    [tous, vue, selections, visibles])); 
end;

*Visibles : Attention il faut distinguer deux visibilités
  • le fait que l'élément ne soit pas visible dans l'arbre parce que son parent n'est pas élargi (IsExpanded=false);
    la propriété de l'élément testée par IsVisible (valeur de la propriété visible de l'élément).

Mis à jour le 1er mars 2019 SergioMaster

Le composant TListView n'a pas de propriété MultiSelect qui, désactivée, permettrait de n'avoir qu'un seul élément sélectionné.
Voici une solution pour un TListView* en mode Édition.

* un TListView dont l'ItemEditAppearance se termine par ShowCheck

Utilisez l'événement OnItemClick du composant.

Code delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
  
procedure TForm1.ListView1ItemClick(const Sender: TObject; 
  const AItem: TListViewItem); 
var anItem : TListViewItem; 
begin 
ListView1.BeginUpdate; 
for anItem in ListView1.Items do 
   anItem.Checked:=(AnItem=AItem) AND AItem.Checked; 
ListView1.EndUpdate; 
end;

Mis à jour le 14 juin 2019 SergioMaster

Réponse simple : utiliser la propriété Sorted.

Code Pascal : Sélectionner tout
ListBox1.Sorted:=True;

Attention, lorsque cette propriété est activée le tri sera appliqué lors de tous les nouveaux ajouts.

Oui mais si je ne veux pas de l'ordre alphabétique (par défaut) ?

La solution "facile" : utiliser l'évènement OnCompare de la ListBox.

Exemple : Ma liste ne contient que des nombres.

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
procedure TForm1.ListBox1Compare(Item1, Item2: TListBoxItem; 
  var Result: Integer); 
var n1,n2 : single; 
begin 
    n1:=StrToFloatDef(Item1.ItemData.Text,0); 
    n2:=StrToFloatDef(Item2.ItemData.Text,0); 
    if n1=n2 then result:=0 
     else begin 
       if n1<n2 then result:=-1 
                else result:=1; 
     end; 
  end; 
end;


Si je veux utiliser une autre valeur que text ?

Première solution : "personnaliser" l'évènement OnCompare en fonction de la colonne.

Exemple 1 : J'ai une ListBox de style DefaultItemStyle.ItemStyle = listboxitemrightdetail et je veux trier en fonction de la "colonne" détail,
la première colonne (texte) contient du texte et la seconde (détail) un montant.

Il faut, en premier lieu déclarer une variable globale (ici ColumnToSort) afin de savoir quelle colonne devra être prise en compte.

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
procedure TForm1.ListBox1Compare(Item1, Item2: TListBoxItem; 
  var Result: Integer); 
var n1,n2 : single; 
begin 
  if ColumnToSort = 0 then 
    result := CompareText(Item1.text,Item2.text) 
  else begin 
    n1:=StrToFloatDef(Item1.ItemData.Detail,0); 
    n2:=StrToFloatDef(Item2.ItemData.Detail,0); 
    if n1=n2 then result:=0 
     else begin 
       if n1<n2 then result:=-1 
                else result:=1; 
     end; 
  end; 
end; 
  
// Utilisation  
procedure TForm1.btnSortDetailClick(Sender: TObject); 
var Compare: TFMXObjectSortCompare; 
begin 
 ListBox1.Sorted:=False; 
 ColumnTosort:=1; 
 Listbox1.Sorted:=true; 
end; 
  
procedure TForm1.btnSortTextClick(Sender: TObject); 
var Compare: TFMXObjectSortCompare; 
begin 
 ListBox1.Sorted:=False; 
 ColumnTosort:=0; 
 Listbox1.Sorted:=true; 
end;


Seconde solution : plus besoin de variable globale, utiliser la procédure Sort().

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
procedure TForm1.btnDetailClick(Sender: TObject); 
var Compare : TFMXObjectSortCompare; 
begin 
ListBox1.Sorted:=False;  // important désactiver le tri "par défaut" 
Compare:=function(item1, item2: TFmxObject): Integer 
  var n1,n2 : Single; 
  begin 
    n1:=StrToFloatDef(TListBoxItem(item1).ItemData.Detail,0); 
    n2:=StrToFloatDef(TListBoxItem(item2).ItemData.Detail,0); 
    if n2=n1 then result:=0 
    else begin 
      if n2>n1 then Result := 1 
               else Result := -1; 
    end; 
  end; 
ListBox1.Sort(Compare); 
ListBox1.RealignContent; // redessine la liste 
end;


BONUS : Comment changer l'ordre de DESCendant en ASCendant et vice-versa ?

Encore une fois cela passera par l'ajout d'une variable booléenne ou autre qui fera office d'indicateur du tri à faire.

Exemple : Application à l'évènement OnCompare, variable globale TriAscendant de type booléen.

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure TForm1.ListBox1Compare(Item1, Item2: TListBoxItem; 
  var Result: Integer); 
var n1,n2 : single; 
begin 
  if ColumnToSort = 0 then 
    result := CompareText(Item1.text,Item2.text) 
  else begin 
    n1:=StrToFloatDef(Item1.ItemData.Detail,0); 
    n2:=StrToFloatDef(Item2.ItemData.Detail,0); 
    if n1=n2 then result:=0 
     else begin 
       if n1<n2 then result:=-1 
                else result:=1; 
     end; 
  end; 
  if TriAscendant then Result:=Result * -1; 
end;

Mis à jour le 29 avril 2020 SergioMaster

Tout d'abord, une remarque : la plupart du temps un TPanel n'est qu'un TRectangle donc si vous voulez changer régulièrement la couleur autant utiliser ce dernier.
Si vous voulez absolument utiliser un TPanel alors voici une astuce simple :

Code Delphi : Sélectionner tout
1
2
3
4
 if (Panel1.ControlsCount >= 1) 
   and (Panel1.Controls[0] is TShape) 
 then 
       (Panel1.Controls[0] as TShape).Fill.Color := TAlphaColorRec.Red;  // uses System.UITypes


Quelques styles FMX utilisent non pas un TRectangle (ou plus génériquement un TShape) comme ressource de style nommée « panelstyle » mais un TCustomStyleObject. Dans ce cas, le changement de couleur de s'applique pas.

Mis à jour le 7 janvier 2022 SergioMaster

Méthode dessin : Utilisation de l'évènement OnDrawColumnHeader

Utilisation de l'unité FMX.TextLayout

Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
procedure TLigne.GrilleDrawColumnHeader(Sender: TObject; 
  const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF); 
var 
  tl: TTextLayout; 
begin 
  tl := TTextLayoutManager.DefaultTextLayout.Create; 
  try 
    tl.BeginUpdate; 
    try 
      // effacer le canvas  
	  // inconvénient la couleur n'est pas sensible au Style appliqué 
      Canvas.Fill.Color := TAlphaColors.LightGrey;  
      Canvas.FillRect(Bounds, 0, 0, [], 1); 
      tl.TopLeft := Bounds.TopLeft; 
      tl.MaxSize := PointF(Column.Width, Column.Height); 
      tl.Font:=GrillePointure.TextSettings.Font; 
      tl.Text := Column.Header; // Value 
      //alignement à gauche TTextAlign.Leading, au centre TTextAlign.Center, à droite TTextAlign.Trailing   
      tl.HorizontalAlign := TTextAlign.Center; 
    finally 
      tl.EndUpdate; 
    end; 
    tl.RenderLayout(Canvas); 
  finally 
    tl.Free; 
  end; 
end;
L'inconvénient de cette technique est que la prise en compte du style est ignorée.
Prendre en compte le style reste possible mais dépendant du fichier style utilisé (hors sujet de cette FAQ).

Je propose donc cette méthode qui fonctionnera quel que soit le fichier style utilisé.

Méthode accès directs aux entêtes : Utilisation de l'unité FMX.Header
Code Delphi : Sélectionner tout
1
2
3
4
5
6
// obtention de l'accès au THeader 
var Header : THeader :=THeader(maGrille.FindStyleResource('header'));   
if assigned(Header) then 
// Changer l'alignement        
//alignement à gauche TTextAlign.Leading, au centre TTextAlign.Center, à droite TTextAlign.Trailing  
TheaderItem(Header.Items[<numcolonne>]).TextSettings.HorzAlign:=TTextAlign.Center;

Mis à jour le 22 juillet 2022 SergioMaster

Mon premier conseil : Anticipez.

Si vous créez les colonnes au runtime, déclarez le bon type :

  • TStringColumn,
  • TDateTimeColumn,
  • TDateColumn,
  • TTimeColumn,
  • TCurrencyColumn,
  • TFloatColumn,
  • TIntegerColumn


plutôt que le type par défaut TColumn (qui est en fait un TStringColumn par défaut). Cela vous permettra d'avoir en plus le bon éditeur associé.

Si vous utilisez LiveBindings pour lier votre grille à des données, durant la conception, déclarez les colonnes (Clic droit sur la grille, option : Éditeur de colonnes) vous pourrez alors, entre autres,
indiquer l'alignement souhaité (propriété Alignment). L'association d'un éditeur se fera (au besoin) en modifiant la propriété ColumnStyle.

Plein d'autres raisons peuvent se liguer pour que ces anticipations ne soient pas possibles.

Il vous reste alors une méthode, l'utilisation de l'évènement OnDrawColumnCell ; cependant la prise en compte des styles est difficile.

Je propose cette méthode qui fonctionnera :
  • quel que soit le fichier style utilisé ;
  • que les colonnes soient déclarées (via l'éditeur de colonne) ou pas.


Ajoutez ce helper au sein de votre unité :
Code Delphi : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
type 
  TColumnHelper = class helper for TColumn 
    procedure ApplyAlignment(Alignment : TTextAlign) ; 
  end; 
... 
implementation  
... 
{TColumnHelper}   
procedure TColumnHelper.ApplyAlignment(Alignment: TTextAlign); 
begin 
  Self.HorzAlign:=alignment; 
  Self.Changed; 
end;

À utiliser de cette manière :
Code Delphi : Sélectionner tout
1
2
// alignement à gauche TTextAlign.Leading, centrer TTextAlign.Center, aligner à droite TTextAlign.Trailing 
StringGrid1.Columns[<numero de colonne>].ApplyAlignment(TTextAlign.Trailing);

Mis à jour le 24 juillet 2022 SergioMaster

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.