Trier un TListView selon une colonne précise !!!

Résolu
alexis2015
Messages postés
73
Date d'inscription
mardi 8 avril 2003
Statut
Membre
Dernière intervention
24 juillet 2005
- 11 sept. 2004 à 20:27
cs_Delphiprog
Messages postés
4297
Date d'inscription
samedi 19 janvier 2002
Statut
Membre
Dernière intervention
9 janvier 2013
- 14 sept. 2004 à 23:32
Voilà j'aimerai savoir cmt je pourrai faire pour moi trier ma liste selon une colonne particulière ! cette dernière comprenant des taille des fichiers!
A voir également:

5 réponses

cs_Delphiprog
Messages postés
4297
Date d'inscription
samedi 19 janvier 2002
Statut
Membre
Dernière intervention
9 janvier 2013
31
11 sept. 2004 à 22:10
La question de Alexis2015 est néanmoins intéressante.

En effet, l'aide en ligne de Delphi propose de trier le contenu de chaque ligne dans une colonne mais...selon un ordre alphabétique.
Donc, un fichier de 12 octets se verra classé devant un fichier de 2 octets dans un classement en ordre croissant. Ca risque de faire désordre !

Voici un code à destination de notre ami qui traitera la deuxième colonne et triera les valeurs selon un ordre numérique :
var
  Sens: boolean; //sens du tri. Inversé à chaque clic sur le titre   d'une colonne

{Compare Int1 et Int 2. Renvoie :
-1 si Int1 < Int2, 
0 si Int1 = Int2
et 1 si Int1 > Int2}
function IsGreater(const Int1, Int2: integer):integer;
begin
  if Int1 > Int2 then
    Result := 1
  else
    if Int1 < Int2 then
      Result := -1
    else
      Result := 0;
end;

function CustomSortProc(Item1, Item2: TListItem; ParamSort: integer): integer; stdcall;
begin
  case ParamSort of
    0: {première colonne}
      begin
        if Sens then
          Result := CompareText(Item1.Caption,Item2.Caption)
        else
          Result := - CompareText(Item1.Caption,Item2.Caption);
      end;

    1: {la colonne contient la taille des fichiers. Il ne faut donc pas
      comparer les valeurs d'après leur code ASCII}
      begin
        if Sens then
           Result := IsGreater(StrToInt(Item1.SubItems[ParamSort - 1]), StrToInt(Item2.SubItems[ParamSort - 1]))
        else
           Result := IsGreater(StrToInt(Item2.SubItems[ParamSort - 1]), StrToInt(Item1.SubItems[ParamSort - 1]));

      end

    else
      if Sens then
        Result := CompareText(Item1.SubItems[ParamSort - 1], Item2.SubItems[ParamSort - 1])
      else
        Result := - CompareText(Item1.SubItems[ParamSort - 1], Item2.SubItems[ParamSort - 1]);
    end {case}
    
end;

procedure TForm1.ListView1ColumnClick(Sender: TObject;
  Column: TListColumn);
begin
  //inversion du sens de classement à chaque clic
  Sens := not Sens;
  //Appel d'une fonction callback de tri personnalisé et passage aussi de la colonne cliquée
  ListView1.CustomSort(@CustomSortProc, Column.Index);
end;


En résumé, ce code traite la deuxième colonne d'un TListView en ordonnant les valeurs selon un ordre numérique, la première et les autres colonnes selon un ordre alphabétique.

L'adaptation à ton problème personnel consiste à remplacer le "1" de "Case ParamSort of 1" par le(s) n° de la colonne(s) que tu souhaites trier selon un ordre numérique.
3
cs_Delphiprog
Messages postés
4297
Date d'inscription
samedi 19 janvier 2002
Statut
Membre
Dernière intervention
9 janvier 2013
31
14 sept. 2004 à 23:32
Petit rappel : 1 Ko = 1024 octets (et non 1000 :) ).
La meilleur précision restant celle de l'octet (et donc une valeur entière).
Si tu veux vraiment utiliser un affichage avec des décimales, la conversion inverse de FloatToStrF est tout simplement StrToFloat.
Ce n'est donc pas tout le code qui est à revoir mais seulemnt la fonction IsGreater (qui, soit dit en passant, aurait dû s'appeler CompareInt pour rester plus cohérente avec CompareText ) et le cas où ParamSort vaut 1.
Le code retouché devient alors :
var
  Sens: boolean;

function CompareNum(const Int1, Int2: integer):integer;overload
begin
  if Int1 > Int2 then
    Result := 1
  else
    if Int1 < Int2 then
      Result := -1
    else
      Result := 0;
end;

function CompareNum(const Float1, Float2: Real):integer;overload;
begin
  if Float1 > Float2 then
    Result := 1
  else
    if Float1 < Float2 then
      Result := -1
    else
      Result := 0;
end;

function CustomSortProc(Item1, Item2: TListItem; ParamSort: integer): integer; stdcall;
begin
  case ParamSort of
    0: {première colonne}
      begin
        if Sens then
          Result := CompareText(Item1.Caption,Item2.Caption)
        else
          Result := - CompareText(Item1.Caption,Item2.Caption);
      end;

    {1: la colonne contient la taille des fichiers. Il ne faut donc pas
      comparer les valeurs d'après leur code ASCII
      begin
        if Sens then
           Result := CompareNum(StrToInt(Item1.SubItems[ParamSort - 1]), StrToInt(Item2.SubItems[ParamSort - 1]))
        else
           Result := CompareNum(StrToInt(Item2.SubItems[ParamSort - 1]), StrToInt(Item1.SubItems[ParamSort - 1]));

      end}
     1: //Idem ci-dessus mais avec des valeurs flottantes
     begin
        if Sens then
           Result := CompareNum(StrToFloat(Item1.SubItems[ParamSort - 1]), StrToFloat(Item2.SubItems[ParamSort - 1]))
        else
           Result := CompareNum(StrToFloat(Item2.SubItems[ParamSort - 1]), StrToFloat(Item1.SubItems[ParamSort - 1]));
     end

    else
      if Sens then
        Result := CompareText(Item1.SubItems[ParamSort - 1], Item2.SubItems[ParamSort - 1])
      else
        Result := - CompareText(Item1.SubItems[ParamSort - 1], Item2.SubItems[ParamSort - 1]);
    end {case}
    
end;

procedure TForm1.ListView1ColumnClick(Sender: TObject;
  Column: TListColumn);
begin
  DecimalSeparator := '.';
  Sens := not Sens;
  ListView1.CustomSort(@CustomSortProc, Column.Index);
end;


Selon le choix que tu feras, la fonction CompareNum adéquate sera appelé par le compilateur.
Tu n'as plus qu'à choisir le cas où ParamSort vaut 1.

Maintenant, c'est à toi de te débrouiller...
3
ZeWaren
Messages postés
24
Date d'inscription
vendredi 11 juin 2004
Statut
Membre
Dernière intervention
22 février 2005

11 sept. 2004 à 21:22
Le TListview possède un evenement onCompare, qui s'execute chaque fois que le TListView compare deux items.
Cherche de la doc dessus (dans l'aide de delphi par exemple...).

Allez, bonne prog !
0
alexis2015
Messages postés
73
Date d'inscription
mardi 8 avril 2003
Statut
Membre
Dernière intervention
24 juillet 2005

12 sept. 2004 à 10:06
merci beaucoup je v jetter un coup d'oeil à ca !
je vous tiens informé ! ;)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
alexis2015
Messages postés
73
Date d'inscription
mardi 8 avril 2003
Statut
Membre
Dernière intervention
24 juillet 2005

14 sept. 2004 à 20:20
revoilà,
code super !
le seul petit hic !
C'est que j'affiche les taille en Ko donc 2 solution s'offre à moi :
1) floattostrf(taille / 1000,fffixed,...)
2) inttostr(taille div 100)

mais j'aimerai avoir une grande précision donc j'opterai + pour la solution 1 mais alors tout le code est à revoir !

J'ai déjà essayé quelque truc mais ca marche pas! [:s]

si vous avez une idée !
0