Ajouter item dans listbox par drag&drop

Résolu
Signaler
Messages postés
259
Date d'inscription
samedi 13 décembre 2003
Statut
Membre
Dernière intervention
22 novembre 2010
-
Messages postés
259
Date d'inscription
samedi 13 décembre 2003
Statut
Membre
Dernière intervention
22 novembre 2010
-
Bonjour,


Voilà j'ai un problème depuis quelques temps qui m'énerve quelque peu car je m'acharne à trouver une solution mais je tourne autour du pot sans trouver une solution.


J'ai créer une ListBox acceptant le drag&drop.
Elle accepte uniquement les formats audio.


Mais voilà je souhaite pouvoir RAJOUTER une fichier audio par la suite sans écraser les autres.
Mais je n'y arrive pas voici ma source :


procedure Tfiche_principale.TraiteMessage(var Msg: TMsg; var Handled: Boolean); // Dans FormCreate, on a mis Application.OnMessage := TraiteMessage;
// c'est donc cette procédure qui est appelée à chaque fois que se déclenche l'évènement OnMessage (c'est à dire à chaque fois que Windows envoie un message à l'application)
// faire attention cette procédure est appelé très souvent par Windows d'où le if dés le départ.
var
  NombreDeFichiers,size,i:integer;
  NomDuFichierStr:string;
  NomDuFichier:array[0..255] of char;
  Nbfichiers: Integer;
begin
  if Msg.message=WM_DROPFILES then
  begin
    NombreDeFichiers:= DragQueryFile( Msg.wParam, $FFFFFFFF, NomDuFichier, sizeof(NomDuFichier));// récupération du nombre de fichiers
    NbFichiers := NombreDeFichiers;
    for i:=0 to NombreDeFichiers-1 do
    begin
      size:= DragQueryFile( Msg.wParam, i, NomDuFichier, sizeof(NomDuFichier) );// récupération du nom du fichier
      NomDuFichierStr:=NomDuFichier; // tansformation du tableau de char en STRING      if ((ExtractFileExt(NomDuFichierStr) '.mp3') or (ExtractFileExt(NomDuFichierStr) '.wma') or (ExtractFileExt(NomDuFichierStr) = '.wav')) then // Vérifie si l'extension des fichiers sélectionnés est bien un fichier audio
      begin // Si c'est le cas...
        if Titres_musiques.Items[0] = '' then // Si la première ligne est vide alors c'est que le tableau est vide
        begin
          Titres_musiques.Clear; // On le vide pour enlever la phrase du drag&drop
          SetLength(Chemin_musiques, NombreDeFichiers); // Règle la taille du tableau
          Chemin_musiques[i] := NomDuFichierStr; // Ajoute le chemin complet de la musique dans le tableau
          Titres_musiques.Items[i] := ExtractFileName(NomDuFichierStr); //Ajoute le titre de la musique dans la ListBox
          ShowMessage(IntToStr(NbFichiers)); //Savoir combien il à détecté de fichiers au moment du drag&drop
          ShowMessage(IntToStr(i)); // Ou en est "i"
        end else
        begin
          SetLength(Chemin_musiques, NombreDeFichiers + NbFichiers);
          Chemin_musiques[i] := NomDuFichierStr;
          Titres_musiques.Items[i] := ExtractFileName(NomDuFichierStr);
          //ShowMessage(IntToStr(NbFichiers));
          //ShowMessage(IntToStr(i));
        end;
      end;
    end;
  end;
end;




Pourriez-vous s'il vous plait me donner une solution qui puisse enfin régler mes problèmes ?


Les "ShowMessage" sont personnels, ils me servent à m'y retrouver justement dans mes tests, mais bon là je bloque...


Merci d'avance

16 réponses

Messages postés
47
Date d'inscription
jeudi 7 septembre 2006
Statut
Membre
Dernière intervention
21 avril 2010

ton code initial fait (tu m'excuseras) un petit peu n'importe quoi, dans la mesure où il refait des SetLength en pagaille


Si préfères ton code à celui de JulioDelphi (qui est très bien), je te conseille les modifs suivantes :


1/ récupère le nb de fichiers déjà dans ta liste (je n'ai pas compris pourquoi tu faisais NbFichiers := NombreFichiers)

NbFichiers := Length(Chemin_musiques);


2/ Fais les manips uniques une seule fois, et pas pour chaque fichier :

if Titres_musiques.Items[0] = '' then

  Titres_musiques.Clear;

SetLength(Chemin_musiques, NbFichiers + NombreFichiers);


// ajoute chacun des fichiers nouvellement "droppés"

for i := 0 to NombreFichiers do

begin

    // récupération du nom du fichier

    size:= DragQueryFile( Msg.wParam, i, NomDuFichier, sizeof(NomDuFichier) );

    NomDuFichierStr:=NomDuFichier; // tansformation du tableau de char en STRING

    sExt := LowerCase(ExtractFileExt(NomDuFichierStr));

    // Vérifie si
l'extension des fichiers sélectionnés est bien un fichier audio

   
if (sExt = '.mp3') or
(sExt= '.wma') or
(sExt = '.wav') then

    begin

       Chemin_musiques[NbFichiers + i] := NomDuFichierStr;

       Titres_musiques.Items[NbFichiers + i] := ExtractFileName(NomDuFichierStr);

    end;

end;    


En plus c'est plus court :-)


Ton pb venait du i au lieu de (NbFichiers + i). Tu écrasais Items[0] avec le premier fichier que tu venais rajouter.
Messages postés
215
Date d'inscription
mardi 29 juillet 2003
Statut
Membre
Dernière intervention
1 septembre 2006

Salut,

Ton problème est assez fréquent.

Pour accepter le Drag&Drop de fichiers depuis l'explorateur Windows, il faut utiliser
l'API DragAcceptFiles. Seulement dans le cas présent, tu veux que ça soit ta ListBox qui accepte le drop de fichiers.

Donc le message WM_DROPFILES lui sera directement envoyé si tu indiques son Handle. C'est pour cela que le message ne passera pas dans la file à destination de ton application(cela m'étonne, j'avoue, mais j'ai fait la constatation après tests).

Deux choix à première vue s'offrent à toi:

- Tu utilises le Handle de ta fiche principale, avec la routine procedure DropFilesMessage(var Msg:TMsg); message WM_DROPFILES; et tu regardes si la souris est dans le rectangle de ta ListBox.

- Tu crées une classe dérivée de TListBox qui capte le message WM_DROPFILES et tu crées un évènement associé(libre cours à ton imagination).

j!nH
Messages postés
259
Date d'inscription
samedi 13 décembre 2003
Statut
Membre
Dernière intervention
22 novembre 2010
2
En fait mon problème ne réside pas dansle fait de pouvoir faire ou non un drag&dropca y'a pas de soucis, mais 'est plus dans le fait de ceci :

- je met par drag&drop deux musiques
- Oh! flut j'enai oublié une je souhaite la rajouter, et donc je prend cette nouvelle musique et je l'ajoute mais ma source ne l'ajoute pas mais la remplace par la première.

Et je cherche le moyen que si je souhaite à rajouter une musique il me le mette à la suite des autres et non pas les remplacer.

Merci en tout cas pour ton explication très précise.

@+
Messages postés
215
Date d'inscription
mardi 29 juillet 2003
Statut
Membre
Dernière intervention
1 septembre 2006

Erf, pourtant ton code ne marchait pas chez moi....

j!nH
Messages postés
259
Date d'inscription
samedi 13 décembre 2003
Statut
Membre
Dernière intervention
22 novembre 2010
2
Oui en effet mon code ne fonctionné pas car jen'aipas mis TOUT le code source permettant justement de faire un drag&drop, mais maintenant si tu testes ce que j'ai dis au dessus tu verras qu'il y'a un problème, et je cherche à trouver un soluce, tu saurais ?
Messages postés
3827
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
16 décembre 2021
46
Salut,

Regarde ton code : il est normal que chaque ajout par un Drag & Drop efface la liste précédente ...
c'est toi qui lui demande : " Titres_musiques.Clear;  "

Le programme ne peut pas lire dans tes pensés, il ne peut donc pas savoir si tu veux ajouter où remplacer les éléments existant.

Il faut revoir la conception du dit programme :
en y ajoutant un bouton " Vider la liste " par exemple
où une CheckBox " Remplacer " 

If  Remplacer.Cheched Then Titres_Musiques.Clear;
// si elle est " Checked " alors on éfface la liste sinon on ajoute à la liste

@+
Cirec
Messages postés
215
Date d'inscription
mardi 29 juillet 2003
Statut
Membre
Dernière intervention
1 septembre 2006

Pfff j'ai pas les yeux en face des trous aujourd'hui...


Merci pour ta clairvoyance Cirec...

j!nH
Messages postés
259
Date d'inscription
samedi 13 décembre 2003
Statut
Membre
Dernière intervention
22 novembre 2010
2
En effet Cirec tu as en partie raison.

Mais si tu suis bien mon programme il n'efface la listbox que quand la ligne N°1 est vide !

if Titres_musiques.Items[0] = '' then  blabla...

(En fait j'ai écrit "Glisser-déposer ici vos musique" mais là la 5e ligne de mon tableau donc les précédentes sont vide voilà pourquoi il faut que je vide mon tableau avant de le remplir.)

Je sais que cela vient du fait que je dois jouer avec une variable pour savoir combien il à d'items jusque là.

Mais mon problème du coup vient du fait qu'il va falloir agrandir le tableau dynamique et là je bloque, donc je suis concincé, tu pourrais continuer à m'aider cirec ?

Le fait de remplacer ne viendra que plus tard, moi je cherche juste pour le moment à ajouter les titres à lasuite rien de plus...
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
38
fonctionnement logique d'un D&D :

Click > glisse > relache = remplace
Click+Ctrl > glisse > relache = ajoute

on peu egalement faire l'inverse :

Click > glisse > relache = ajoute
Click+Alt > glisse > relache = remplace

car on associe toujours Ctrl a + et Alt a -

<hr size="2" width="100%" />Croc (click me)
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
38
aller voila le code complet d'un D&D de fichiers simple et efficace...

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
    procedure ListBoxDrop(var msg : TWMDropFiles) ; message WM_DROPFILES;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses ShellApi;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DragAcceptFiles(ListBox1.Handle, True);
  ListBox1.Style := lbOwnerDrawVariable;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DragAcceptFiles(ListBox1.Handle, false);
end;

procedure TForm1.ListBoxDrop(var msg: TWMDropFiles);
var
  i,
  BufferSize,
  FilesCount : integer;
  FileName   : string;
begin
  FilesCount := DragQueryFile(msg.Drop, $FFFFFFFF, nil, 0);
  BufferSize := MAX_PATH;
  SetLength(FileName, BufferSize);

  ListBox1.Items.BeginUpdate;

  for i:= 0 to FilesCount-1 do begin
    DragQueryFile(msg.Drop, i, PChar(FileName), BufferSize);
    ListBox1.Items.Add(FileName);
  end;

  ListBox1.Items.EndUpdate;
end;

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
  with ListBox1 do begin
       Canvas.FillRect(Rect);
       Canvas.TextRect(Rect,Rect.Left+2,Rect.Top+2,ExtractFileName(Items[index]));
  end;
end;

end.

<hr size="2" width="100%" />Croc (click me)
Messages postés
4202
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
38
petite modif pour eviter les doublons,  supprimer les lignes vides et les liens morts a l'ajout :

procedure TForm1.ListBoxDrop(var msg: TWMDropFiles);
var
  i,
  BufferSize,
  FilesCount : integer;
  FileName   : string;
  TempList   : TStringList;
begin
  FilesCount := DragQueryFile(msg.Drop, $FFFFFFFF, nil, 0);

  // suppression des doublons
  TempList            := TStringList.Create;
  TempList.Sorted     := true;
  TempList.Duplicates := dupIgnore;
  TempList.Assign(ListBox1.Items);

  // suppression des chaines vides et des liens morts
  for i := TempList.Count-1 downto 0 do
      if (Length(TempList.Strings[i]) = 0) or (not FileExists(TempList.Strings[i])) then
         TempList.Delete(i);
 
  // ajout des fichiers
  BufferSize := MAX_PATH;
  SetLength(FileName, BufferSize);
  for i:= 0 to FilesCount-1 do begin
    DragQueryFile(msg.Drop, i, PChar(FileName), BufferSize);
    TempList.Add(FileName);
  end;

  // mise a jours de la liste
  ListBox1.Items.BeginUpdate;
  ListBox1.Items.Assign(TempList);
  ListBox1.Items.EndUpdate;

  TempList.Free;
end;

<hr size="2" width="100%" />Croc (click me)
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
14
je testerais ce source demain matin, mais juste a lire je ne comprends pas un truc :
si la ligne 1 (index 0) est vide, alors on vide la liste. si je ne me trompe pas, si la ligne 1 est vide, la liste l'est aussi non ? a quoi sert cette verif ?
Messages postés
259
Date d'inscription
samedi 13 décembre 2003
Statut
Membre
Dernière intervention
22 novembre 2010
2
Si tu relis bien mes messages je dis justement que non la liste n'est pas vide m'ais qu'il y'a un message à la 5e ligne et que les 4eres sont vides, c'est pour cette raison que je fais cetet vérification.

@+
Messages postés
2226
Date d'inscription
dimanche 5 octobre 2003
Statut
Modérateur
Dernière intervention
18 novembre 2010
14
ha oui ok j'avais sauté par dessus les parenthèses :D
me reste a comprendre pourquoi tu laisse des lignes vide jusqu'a la 5eme
Messages postés
47
Date d'inscription
jeudi 7 septembre 2006
Statut
Membre
Dernière intervention
21 avril 2010

pardon, j'ai confondu (honte à moi !) c'était le code de f0xi !

veuillez agréer un millier de mes plus plates excuses

(je retourne au primaire pour apprendre à lire)
Messages postés
259
Date d'inscription
samedi 13 décembre 2003
Statut
Membre
Dernière intervention
22 novembre 2010
2
Merci pour toutes ces réponses, j'ai acceptée celle que j'ai la mieux comprise, mais je garde de côté toutes les autres sources car elle pourront grandement mer servir à l'avenir !!!

@+