| Autor |
Beitrag |
MILÖ
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: Sa 01.01.05 16:37
Ich habe eine Form mit einer DirectoryListBox und einem ListView.
Das ListView hat zwei Spalten. In der ersten Spalte werden die Dateinamen und in der zweiten Spalte die Dateigröße angezeigt. Wenn ich jetzt auf die erste Spalte klicke, soll nach Dateinamen sortiert werden, was auch klappt.
Wenn ich jetzt auf die zweite Spalte klicke, dann soll nach Dateigröße sortiert werden. Das klappt aber nicht!
ACHTUNG! Bitte nur Lösungen anbieten, die auch unter Delphi 3.0 funktionieren.
Die Tipps www.delphi-forum.de/...t=listview+sortieren habe ich schon gesehen. Haben aber das 3.0 Problem nicht gelößt. Deshalb der Code, welcher ja schon für die erste Spalte funktioniert.
Hier der Code....
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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140:
| unit Unit3; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,SystemSP, ComCtrls, FileCtrl, ExtCtrls; type TForm1 = class(TForm) ListView1: TListView; DirectoryListBox1: TDirectoryListBox; procedure Button3Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn); procedure ListView1Compare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); private MyList: TStringList; Name,Path:string; Attr:Word; public end; var Form1: TForm1; implementation {$R *.DFM} var SearchRec: TSearchRec; ColumnToSort : Integer; Accending : Boolean = False; procedure TForm1.FormCreate(Sender: TObject); begin Button3Click(Form1); DirectoryListBox1.OnChange:=Button3Click; end;
procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn); function DateSortProc(Item1, Item2: TListItem; ParamSort: Integer): Integer; stdcall; begin Result := CompareText(Item1.Caption,Item2.Caption); end;
begin case Column.Index of 0: ListView1.CustomSort(@DateSortProc, 0); 1: ListView1.CustomSort(@DateSortProc, 1); end; end;
procedure TForm1.ListView1Compare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); begin case ColumnToSort of 0: begin if Accending then Compare := CompareText(Item1.Caption, Item2.Caption) else Compare := CompareText(Item2.Caption, Item1.Caption); end; 1: begin if Accending then Compare := StrToInt(Item1.SubItems[0]) - StrToInt(Item2.SubItems[0]) else Compare := StrToInt(Item2.SubItems[0]) - StrToInt(Item1.SubItems[0]); end; end; end;
procedure TForm1.Button3Click(Sender: TObject); var NewItem : TListItem; x,Result:integer; DT:string; begin MyList := TStringList.Create; Attr:=faAnyFile; Path:=DirectoryListBox1.Directory; if (Length(Path) = 2) or (Length(Path) > 3) then Path := Path+'\'; Result:=FindFirst(Path+'*.*', Attr, SearchRec); MyList.Sorted := True; ListView1.Items.Clear; If not ((SearchRec.Name='') or (SearchRec.Name='.') or (Result<>0))then Begin NewItem := ListView1.Items.Add; NewItem.Caption := SearchRec.Name; If SearchRec.Attr<> 16 then NewItem.SubItems.Add(IntToStr(SearchRec.Size)) else NewItem.SubItems.Add('Dateiordner'); try DateTimeToString(DT,'dd.mm.yy t',FileDateToDateTime(SearchRec.Time)); NewItem.SubItems.Add(DT); except NewItem.SubItems.Add(''); end; NewItem.SubItems.Add(IntToStr(SearchRec.Attr)); end; While Result = 0 do Begin Result:=FindNext(SearchRec); If not ((SearchRec.Name='.') or (SearchRec.Name='..') or (Result<>0)) then Begin NewItem := ListView1.Items.Add; NewItem.Caption := SearchRec.Name; If SearchRec.Attr<> 16 then NewItem.SubItems.Add(IntToStr(SearchRec.Size)) else NewItem.SubItems.Add('Dateiordner'); try DateTimeToString(DT,'dd.mm.yy t',FileDateToDateTime(SearchRec.Time)); NewItem.SubItems.Add(DT); except NewItem.SubItems.Add(''); end; NewItem.SubItems.Add(IntToStr(SearchRec.Attr)); end; end; MyList.Destroy; end; end. |
Was mus geändert werden?
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 01.01.05 17:56
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn); function DateSortProc(Item1, Item2: TListItem; ParamSort: Integer): Integer; stdcall; begin // Datum absteigend sortieren, falls aufsteigend erwünscht // minus-Zeichen weglassen Result := CompareText(Item1.Caption,Item2.Caption); end; begin case Column.Index of 0: ListView1.CustomSort(@DateSortProc, 0); 1: ListView1.CustomSort(@DateSortProc, 1); end; end; |
zeig mir mal bitte, wo du das her hast. Luckie hat sich extra die Mühe gemacht und hat dir ein Beispiel geschrieben. Und es war sinnlos, sorry, aber du mußt dich schon mit den Sachen auseinandersetzen. Da in dem code was vom "datum" steht, du überhaupt kein Datum hast, ist der code schonmal nicht von dir. und jetz überleg mal, was in dem code überhaupt passiert:
-> eine Spalte wird angeklickt und du landest im oncolumnsclick-ereignis.
-> der columnindex wird ausgewertet (case bei dir im code) und du rufst dann customsort auf, der dabei übergebene Paramete "Paramsort" ist sinnlos, da er überhaupt nicht verwendet wird. Außerdem ist er für die Sortierreihenfolge (auf oder absteigend) bestimmt, nicht für die Sortierspalte.
-> bei DateSortProc wird auch immer nur die Caption (also die erste Spalte) ausgewertet und nach dieser wird auch sortiert. Von der 2. Spalte ist hier überhaupt nicht die Rede, also kann auch nie nach der 2. Spalte sortiert werden.
Ich habe zur Zeit kein D3 installiert, glaube aber nicht, das sich die OH sich in diesem Punkt von meinem d6 unterscheidet.
| OH hat folgendes geschrieben: |
Mit einer Ereignisbehandlungsroutine für OnCompare können Sie eine Sortierreihenfolge für die Liste implementieren. Die Ereignisbehandlungsroutine wird aufgerufen, wenn die Eigenschaft SortType auf stData oder stBoth gesetzt ist und entweder die Methode CustomSort ohne den Parameter SortProc oder die Methode AlphaSort aufgerufen wird.
|
Du mischst hier 2 Dinge. Entweder du verwendest custumsort und eine sortierprozedure oder wie Luckie alphasort und oncompare (würde ich auch favorisieren) . wenn du customsort verwendest, kannst du dir oncompare sparen.
Luckie 1: 2: 3: 4: 5: 6: 7:
| procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn); begin ColumnToSort := Column.Index; <<<<----- hier wird die Spalte angeben, nach der sortiert wird und diese wird bei oncompare ausgewertet. Listview1.AlphaSort; Accending := not Accending; end; |
warum hast du nicht den code von Luckie verwendet???
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
MILÖ 
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: Sa 01.01.05 18:51
@ Keldorn
Ich habe schon auch den Code von Luckie verwendet und nur die procedure FindAllFiles und die function GetFileSize durch Button3Click ersetzt.
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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116:
| type TForm1 = class(TForm) ListView1: TListView; DirectoryListBox1: TDirectoryListBox; procedure Button3Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn); procedure ListView1Compare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); private MyList: TStringList; Name,Path:string; Attr:Word; public end;
var Form1: TForm1;
implementation
{$R *.dfm}
var ColumnToSort : Integer; Accending : Boolean = False; SearchRec: TSearchRec;
procedure TForm1.Button3Click(Sender: TObject); var NewItem : TListItem; x,Result:integer; DT:string; begin MyList := TStringList.Create; Attr:=faAnyFile; Path:=DirectoryListBox1.Directory; if (Length(Path) = 2) or (Length(Path) > 3) then Path := Path+'\'; Result:=FindFirst(Path+'*.*', Attr, SearchRec); MyList.Sorted := True; ListView1.Items.Clear; If not ((SearchRec.Name='') or (SearchRec.Name='.') or (Result<>0))then Begin NewItem := ListView1.Items.Add; NewItem.Caption := SearchRec.Name; If SearchRec.Attr<> 16 then NewItem.SubItems.Add(IntToStr(SearchRec.Size)) else NewItem.SubItems.Add('Dateiordner'); try DateTimeToString(DT,'dd.mm.yy t',FileDateToDateTime(SearchRec.Time)); NewItem.SubItems.Add(DT); except NewItem.SubItems.Add(''); end; NewItem.SubItems.Add(IntToStr(SearchRec.Attr)); end; While Result = 0 do Begin Result:=FindNext(SearchRec); If not ((SearchRec.Name='.') or (SearchRec.Name='..') or (Result<>0)) then Begin NewItem := ListView1.Items.Add; NewItem.Caption := SearchRec.Name; If SearchRec.Attr<> 16 then NewItem.SubItems.Add(IntToStr(SearchRec.Size)) else NewItem.SubItems.Add('Dateiordner'); try DateTimeToString(DT,'dd.mm.yy t',FileDateToDateTime(SearchRec.Time)); NewItem.SubItems.Add(DT); except NewItem.SubItems.Add(''); end; NewItem.SubItems.Add(IntToStr(SearchRec.Attr)); end; end; MyList.Destroy; end;
procedure TForm1.FormCreate(Sender: TObject); begin Listview1.SortType := stData; Button3Click(Form1); DirectoryListBox1.OnChange:=Button3Click; end;
procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn); begin ColumnToSort := Column.Index; Listview1.AlphaSort; Accending := not Accending; end;
procedure TForm1.ListView1Compare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); begin case ColumnToSort of 0: begin if Accending then Compare := CompareText(Item1.Caption, Item2.Caption) else Compare := CompareText(Item2.Caption, Item1.Caption); end; 1: begin if Accending then Compare := StrToInt(Item1.SubItems[0]) - StrToInt(Item2.SubItems[0]) else Compare := StrToInt(Item2.SubItems[0]) - StrToInt(Item1.SubItems[0]); end; end; end; |
Leider funktioniert das bei mir nicht. Ich weiß, dass es bei ihm funktioniert. Er hat mir ja auch eine exe Datei geschickt und da geht alles super....
Ich denke mal, dass ich keine Lösung für 3.0 finden werde.
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 01.01.05 19:34
| MILÖ hat folgendes geschrieben: |
Leider funktioniert das bei mir nicht. |
ich kann mir darunter nichts vorstellen, das mußt du schon genauer beschreiben - gibts Fehlermeldungen etc. ?
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Sa 01.01.05 19:44
Angeblich würde diese zeile
Delphi-Quelltext 1:
| Listview1.SortType := stData; |
unter D3 nicht gehen, was auch immer sdas heißt. Ich kann mir aber nicht vorstellen, dass der Listview unter D3 keinen SortTyp kennt bzw die Eigenschaft tsData unbekannt ist.Das kannst du übrignes auch im ObjektInspektor einstellen, das muss nicht im Code gemacht werden.
|
|
MILÖ 
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: Sa 01.01.05 19:54
@ Luckie
Hallo Das habe ich doch gar nicht geschrieben, dass Listview1.SortType := stData; nicht funktioniert. Ich habe es doch auch in meinem Code unter FormCreate.
Ich habe lediglich geschrieben, dass beim Klick auf die erste Spalte (Namen) die Sortierung nach Namen funktioniert und bei einem Klick auf die zweite Spalte (Grösse) es nicht funktioniert das nach der Dateigröße sortiert wird.
Ich weiß, in deinem Script, welches Du mir geschickt hast, funktioniert es so wie ich es mir vorstelle. Nur leider bei mir nicht. Es gibt keine Fehlermeldungen bei dem obigen Code. Die Meldungen gab es nur als ich die Procedure FindAllFiles und die Funktion GetFileSize genutz habe, aber die habe ich ja ersetzt.
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 01.01.05 20:12
so, D3 wieder installiert
| Luckie hat folgendes geschrieben: | Angeblich würde diese zeile
Delphi-Quelltext 1:
| Listview1.SortType := stData; |
unter D3 nicht gehen, was auch immer sdas heißt. |
nein, das geht.
@milö: ich habe den code von oben übernommen und ... er geht.
lediglich bei Verzeichnissen, wo nicht nur Dateien sondern auch Verzeichnisse enthalten sind, kracht es an der Stelle
| Zitat: |
Compare := StrToInt(Item1.SubItems[0]) - StrToInt(Item2.SubItems[0])
|
da du hier versuchst, "Dateiordner" in ein Zahl zu wandeln. Da du von keinen Fehlermedlungen berichtet hast, kanns das aber auch nicht sein.
habs in
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.ListView1Compare(Sender: TObject; Item1, Item2: TListItem; Data: Integer; var Compare: Integer); Var z1,z2,code:integer; begin case ColumnToSort of 0: Compare := CompareText(Item1.Caption, Item2.Caption); 1: begin z1:=0; z2:=0; val(Item1.SubItems[0],z1,code); val(Item2.SubItems[0],z2,code); compare:=z1-z2; end; end; if accending then compare:=not compare; end; |
geändert.
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
MILÖ 
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: Sa 01.01.05 20:52
Habe ich geändert und siehe:
Es funktioniert auch nicht. Bei einem Klick auf die zweite Spalte (Grösse)
Nur die erste Spalte (Namen) kann man sortieren.
Ich verzweifel langsamm.... 
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 01.01.05 21:08
hab deine PN erhalten und habs mir runtergeladen und es ist ganz einfach  . du hast zwar das oncompare-ereignis in deinen code reingeschreiben, es aber nicht im Objectinspektor bei listview-oncompare zugewiesen. Deswegen wird auch nur 1x sortiert und nicht auf oder absteigend und du siehst auch keine exception bei Ordnern, da dein oncompare im code überhaupt nicht angesprochen wird.
Mfg Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
MILÖ 
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: Sa 01.01.05 21:35
 DANKE.....
Jetzt noch eine kleine Frage und ich bin Glücklich...
Ich möchte auf einen Eintrag in der Liste einen Doppelklick machen und dann den Dateinamen im einem Memo erhalten. Oder mehrere Einträge auswählen um sie dann z.B. in ein Memo zu übertragen.
In einer FileListBox würde ich das z.B. so machen:
Delphi-Quelltext 1: 2:
| For i:=0 to FileListBox1.Count do if FileListBox1.Selected[i] then Memo1.Lines.Add(FileListBox1.Items[Wert]); |
Ich weiß, das geht so in einem ListView natürlich nicht.
Falls sich hier jemand fragt, warum das Ganze. Ganz einfach ich habe vor langer Zeit mal ein Programm geschrieben.
123 Change zum komfortablen ändern von Dateinamen in ganzen Verzeichnissen. Man gibt den Dateinamen vor und Change ändert bei allen ausgewählten Dateien den Dateinamen und nummeriert sie fortlaufend.
Und diese Programm wollte ich einfach so ändern, so das man die Dateien vorher sortieren kann.
Das Programm findet man kostenlos auf meiner HP
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 01.01.05 21:41
| MILÖ hat folgendes geschrieben: |
Ich möchte auf einen Eintrag in der Liste einen Doppelklick machen und dann den Dateinamen im einem Memo erhalten. Oder mehrere Einträge auswählen um sie dann z.B. in ein Memo zu übertragen.
|
1. neue Frage, neuer Thread
| Zitat: |
In einer FileListBox würde ich das z.B. so machen:
Delphi-Quelltext 1: 2:
| For i:=0 to FileListBox1.Count do if FileListBox1.Selected[i] then Memo1.Lines.Add(FileListBox1.Items[Wert]); |
|
2. glaub ich nicht, FileListBox1.Count-1 wäre richtig.
| Zitat: |
Ich weiß, das geht so in einem ListView natürlich nicht.
|
3.
Delphi-Quelltext 1: 2:
| for i:=0 to listview1.items.count-1 do if listview1.items[i].Selected then ... |
Mfg Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
MILÖ 
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: Sa 01.01.05 21:50
Habe ich gemacht:
Delphi-Quelltext 1: 2:
| for i:=0 to listview1.items.count-1 do if listview1.items[i].Selected then Memo1.Lines.Add(listview1.items[i]); |
Und dann bekomme ich diesen Fehler:
| Zitat: | | Incompatible types: 'String' and 'TListItem' |
|
|
Keldorn
      
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 01.01.05 21:54
ein listitem besteht nunmal aus caption und subitems
also z.B.
Delphi-Quelltext 1:
| Memo1.Lines.Add(listview1.items[i].caption); |
oder
Delphi-Quelltext 1:
| Memo1.Lines.Add(listview1.items[i].caption+' '+listview1.items[i].subitems[0]); |
neuer Frage- neuer Thread!!
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
MILÖ 
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: Sa 01.01.05 21:57
Danke  Keldorn Du hast mir sehr geholfen.
Ich muss schon sagen ein SUPER Forum hier.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 02.01.05 11:23
| Keldorn hat folgendes geschrieben: | | du hast zwar das oncompare-ereignis in deinen code reingeschreiben, es aber nicht im Objectinspektor bei listview-oncompare zugewiesen. |
Das darf ja wohl nicht waht sein! In dem anderen Thread habe ich extra noch geschrieben, dass die Ereignisse natütlich zu geordnet werden müssen. 
|
|
MILÖ 
      
Beiträge: 26
WIN 98 SE
Delphi 3.0
|
Verfasst: So 02.01.05 13:29
@ Luckie
Keldorn hat sich aber die Mühe gemacht, sich meinen Code mal anzuschauen.
Du hattest mir geschrieben, dass Du keine Lust hat mir alles aus der Nase ziehen zu müssen. Ich hatte Dir meinen Code ja auch geschickt.
Ich bin halt kein Experte in Delphi und deshalb habe ich mich ja auch an dieses Forum gewannt.
Also nochmals danke an Keldorn, welcher extra hierfür D3 installiert hat.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 02.01.05 16:07
Wenn ich mir jeden Code angucken würde, der mir zugeschickt wird, dann könnte ich nichts anderes mehr machen.  Normalerweise reagiere ich auf Mails bezüglich Delphi gar nicht, es sei denn es geht um Code von mir.
|
|
|