Ajouter item dans listbox par drag&drop

Résolu
Also know as Messages postés 259 Date d'inscription samedi 13 décembre 2003 Statut Membre Dernière intervention 22 novembre 2010 - 28 août 2006 à 12:20
Also know as Messages postés 259 Date d'inscription samedi 13 décembre 2003 Statut Membre Dernière intervention 22 novembre 2010 - 21 sept. 2006 à 18:42
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

yopai_v Messages postés 47 Date d'inscription jeudi 7 septembre 2006 Statut Membre Dernière intervention 21 avril 2010
21 sept. 2006 à 13:30
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.
3
jinh68 Messages postés 215 Date d'inscription mardi 29 juillet 2003 Statut Membre Dernière intervention 1 septembre 2006
28 août 2006 à 13:03
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
0
Also know as Messages postés 259 Date d'inscription samedi 13 décembre 2003 Statut Membre Dernière intervention 22 novembre 2010 2
28 août 2006 à 13:17
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.

@+
0
jinh68 Messages postés 215 Date d'inscription mardi 29 juillet 2003 Statut Membre Dernière intervention 1 septembre 2006
28 août 2006 à 13:19
Erf, pourtant ton code ne marchait pas chez moi....

j!nH
0

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

Posez votre question
Also know as Messages postés 259 Date d'inscription samedi 13 décembre 2003 Statut Membre Dernière intervention 22 novembre 2010 2
28 août 2006 à 13:25
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 ?
0
Cirec Messages postés 3833 Date d'inscription vendredi 23 juillet 2004 Statut Modérateur Dernière intervention 18 septembre 2022 50
28 août 2006 à 13:47
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
0
jinh68 Messages postés 215 Date d'inscription mardi 29 juillet 2003 Statut Membre Dernière intervention 1 septembre 2006
28 août 2006 à 14:13
Pfff j'ai pas les yeux en face des trous aujourd'hui...


Merci pour ta clairvoyance Cirec...

j!nH
0
Also know as Messages postés 259 Date d'inscription samedi 13 décembre 2003 Statut Membre Dernière intervention 22 novembre 2010 2
28 août 2006 à 15:56
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...
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
29 août 2006 à 04:35
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)
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
29 août 2006 à 05:05
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)
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
29 août 2006 à 05:24
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)
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
29 août 2006 à 18:48
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 ?
0
Also know as Messages postés 259 Date d'inscription samedi 13 décembre 2003 Statut Membre Dernière intervention 22 novembre 2010 2
29 août 2006 à 20:49
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.

@+
0
JulioDelphi Messages postés 2226 Date d'inscription dimanche 5 octobre 2003 Statut Membre Dernière intervention 18 novembre 2010 14
29 août 2006 à 21:46
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
0
yopai_v Messages postés 47 Date d'inscription jeudi 7 septembre 2006 Statut Membre Dernière intervention 21 avril 2010
21 sept. 2006 à 13:37
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)
0
Also know as Messages postés 259 Date d'inscription samedi 13 décembre 2003 Statut Membre Dernière intervention 22 novembre 2010 2
21 sept. 2006 à 18:42
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 !!!

@+
0
Rejoignez-nous