![]() |
VirtualStringTree - Nodes hinzufügen
hallo, nach einigen stunden habe ich es endlich hinbekommen die komponente VST zu installieren.
ich bin aber irgendwie schockiert. denn die komponente ist so dermaßen mächtig und doch möchte ich doch nur Nodes hinzufügen. mit einer listview ging es so:
Delphi-Quellcode:
wie bekomme ich das mit der VST so hin? ich habe die VST schon im Stil eines ListView (vsReport) mit zwei Spalten.
var MeinItem: TListItem;
begin MeinItem:= ListView1.Items.Add; MeinItemChecked := True; MeinItemCaption := 'Item Caption'; MeinItemAdd('SubItem Caption'); end; aber wie füge ich etwas hinzu =/ |
AW: VirtualStringTree - Nodes hinzufügen
update:
ich schaffe es mittlerweile nodes aus einer dateiliste hinzuzufügen, diese korrekt und farblich darzustellen. das funktioniert alles wunderbar und schnell. doch wenn ich GetImageIndex verwende ist die VST sehr sehr träge und langsam. zudem werden nicht alle icons angezeigt. die systemicons hole ich so:
Delphi-Quellcode:
komischerweise sind auch nur 7 icons in der ImageList zu anfang.
// private deklariert
hImgSm: HIMAGELIST; aFileIcon: TSHFileInfo; // ... // OnCreate: hImgSm := HIMAGELIST(SHGetFileInfo('', 0, aFileIcon, SizeOf(aFileIcon), SHGFI_SYSICONINDEX or SHGFI_ICON)); if (hImgSm <> 0) then ImageList1.Handle := hImgSm; ImageList1.ShareImages := True; VST.Images := ImageList1; // ... procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: integer); var Data: PTreeData; begin Data := VST.GetNodeData(Node); begin ZeroMemory(@aFileIcon, SizeOf(aFileIcon)); if SHGetFileInfo(PChar(Data.sFileName), 0, aFileIcon, SizeOf(aFileIcon), SHGFI_SYSICONINDEX or SHGFI_ICON) <> 0 then begin ImageIndex := aFileIcon.iIcon; end; end; end; |
AW: VirtualStringTree - Nodes hinzufügen
Lerne von denen, die das professionell machen ;)
Wenn ich mir den Windows-Explorer anschaue, dann werden dort erst nur die Dateinamen angezeigt und einen kleinen Augenblick später erscheinen die Icons (sieht man sehr schön, wenn die Kiste mal gut ausgelastet ist). Die Icons und andere Zusatzinformationen werden per Thread geladen und dann nach und nach erst angezeigt. |
AW: VirtualStringTree - Nodes hinzufügen
Zitat:
Wie das jetzt ist weiß ich nicht, dafür sind die Rechner zu schnell, aber gelegentlich bin ich der Meinung noch einen Standard-Icon für kurze Zeit zu sehen. In Grunde ist das aber das gleiche, denn ob man kein Icon zuweist oder ein Standard-Icon, ist ja die gleiche Zeit. |
AW: VirtualStringTree - Nodes hinzufügen
ok das werde mir mal angucken. ich habe es bereits etwas umgestellt:
Delphi-Quellcode:
mit diesem gut war alles in ordnung. aber, ich weiß nicht seit wann, seit geraumer zeit sind die icons nicht mehr sichtbar. sie blitzen nur auf wenn ich scrolle.
procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind;
Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: integer); var Data: PTreeData; Icon: TIcon; begin Data := VST.GetNodeData(Node); if (not Data.bUpdated) and (Column = 0) then begin Icon := TIcon.Create; ZeroMemory(@aFileIcon, SizeOf(aFileIcon)); SHGetFileInfo(PChar(Data.sFileName), 0, aFileIcon, SizeOf(aFileIcon), SHGFI_SYSICONINDEX or SHGFI_ICON); Icon.Handle := aFileIcon.hIcon; ImageIndex := ImageList1.AddIcon(Icon); Data.bUpdated := True; Icon.Free; end; end; ein wort zu dem bUpdated: wenn ich das nicht hinzufüge, dann "zeichnet" mein prozessor sich tot (cpu-last konstant 100). |
AW: VirtualStringTree - Nodes hinzufügen
Hi.
wenn du versuchst Windows-Explorer nachzubauen, es gibt schon eine fertige lösung dafür. und zwar die ![]() |
AW: VirtualStringTree - Nodes hinzufügen
Liste der Anhänge anzeigen (Anzahl: 1)
danke für den zipp aber das versuche ich nicht =)
zu meinem problem mit den icons die verschwunden sind und nur auftauchen wenn ich scrolle: siehe screenshot. der rot markierte kasten ist ein screenshot genau dann wann ich schnell scrolle. P.S.: und warum die CheckBox in column 1 ist und nicht in 0 weiß ich auch nicht =/ daten in treeview bringen:
Delphi-Quellcode:
var
TreeData: TTreeData; // ... VST.NodeDataSize := SizeOf(TTreeData); TreeData.a:= sl.Strings[i]; TreeData.b:= IntToStr(getFileSizeA(TreeData.sFileName)); TreeData.c:= DateTimeToStr(getFileLastModified(TreeData.sFileName)); TreeData.d:= '=>'; TreeData.e:= sl.Strings[i]; TreeData.f:= ''; TreeData.g:= ''; TreeData.bUpdated := False; AddVSTStructure(VST, TreeData); // ... function AddVSTStructure(aVST: TVirtualStringTree; aRecord: TTreeData): PVirtualNode; var Data: PTreeData; begin Result := aVST.AddChild(nil); Result.CheckType := ctCheckBox; Result.CheckState := csCheckedNormal; Data := aVST.GetNodeData(Result); aVST.ValidateNode(Result, False); Data^ := aRecord; end; |
AW: VirtualStringTree - Nodes hinzufügen
@Popov
Ich bezog mich schon auf die aktuelleren Windows-Versionen ;) So ist es, erst ist dort ein Standard-Icon und dann wird das übermalt/ersetzt. |
AW: VirtualStringTree - Nodes hinzufügen
Delphi-Quellcode:
Hier sieht man, dass du dein Icon direkt liest und speicherst. Das kostet Zeit. Ich habe in dem anderen Thread doch dieses Beispiel gepostet. Eine Seite weiter habe ich paar Änderungen gepostet. Da greift das Beispiel auf die ImageListe vom System und holt sich nur noch den ImageIndex. Guck dir das mal an. Zumindest brauchst du den Ordner-Icon nicht zig mal zu laden, sondern nur einmal.
SHGetFileInfo(PChar(Data.sFileName), 0, aFileIcon, SizeOf(aFileIcon), SHGFI_SYSICONINDEX or SHGFI_ICON);
Icon.Handle := aFileIcon.hIcon; ImageIndex := ImageList1.AddIcon(Icon); |
AW: VirtualStringTree - Nodes hinzufügen
das mit dem system-icon hatte ich vorher in einer listview schon eingesetzt. aber komischerweise werden bei der VST ungefähr 90% der icons nicht geladen.
momentan habe ich eh das problem dass gar keine icons angezeigt werden und ich verstehe nicht wieso (siehe posting open mit screenshot). ich bin echt zufrieden mit dieser komponente. aber es gibt viele dinge die ich vermisse und ich habe keine ahnung wie man das macht. z.b. vermisse ich MeinItem.SubItemImages[X] usw. generell. zudem wird meine checkbox nicht korrekt positioniert. leider weiß ich nicht wie man eine checkbox bei virtuellem modus in eine listiew zeichnet. dann würde ich VST nicht nutzen müssen. siehe hier: ![]() |
AW: VirtualStringTree - Nodes hinzufügen
kleiner zwischenbericht:
- checkbox ist nun korrekt positioniert, dank dem property "MainColumn". - die items werden nun dank dieses threads korrekt angezeigt und verschwinden auch nicht mehr: ![]() das andere problem mit den images in den anderen columns habe ich auch bereits gelöst. wenn ich alle dateien und verzeichnisse aus C:\Windows\System32 in eine stringliste lade und die VST dann mit nodes fülle (listview-artig mit 6 spalten) dauert das ganze nun 4 sekunden. mit einer listview dauert das mehr als 20. ich füge nicht nur hinzu ich ändere auch schrift- und hintergrundfarben manchmal + es sind checkboxen vorhanden. bei biden varianten dauert die erstellung der stringliste rund 400ms. sind 4 sekunden für alles in ordnung oder ist das für 13000 einträge mit schöner darstellung zu lange? |
AW: VirtualStringTree - Nodes hinzufügen
Das Problem warum es bei dir so lange dauert ist das Hinzufügen. Eigentlich ist genau das schöne an der VST, dass du die Knoten hinzufügen kannst und diese nicht direkt abgerufen werden, erst wenn du sie anzeigst. Du rufst aber unnötigerweise ValidateNode auf und führst das damit ad absurdum. ;-)
Eine Möglichkeit
Delphi-Quellcode:
Das ist immer noch nicht optimal, da jede Datei aus dem Thread einzeln synchronisiert und angezeigt wird. Da könnte man auch z.B. alle Dateien in einem Verzeichnis in eine Liste packen und die ganze Liste synchronisiert hinzufügen oder ähnliches. Aber das sollte als beispiel erst einmal reichen. ;-)
type
TTreeData = class private FFilename: string; FIconIndex: Integer; public constructor Create(const AFilename: string); property IconIndex: Integer read FIconIndex write FIconIndex; property Filename: string read FFilename write FFilename; end; TOnAddFile = procedure(const AFilename: string) of object; TFileSearchTree = class(TThread) private FPath: string; FOnAddFile: TOnAddFile; FCurrentFile: string; procedure DoAddFile; protected procedure Execute; override; public constructor Create(const APath: string; const AOnAddFile: TOnAddFile); property OnAddFile: TOnAddFile read FOnAddFile write FOnAddFile; end; TForm67 = class(TForm) VST: TVirtualStringTree; ImageList1: TImageList; procedure FormCreate(Sender: TObject); procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); procedure VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); private procedure AddFile(const AFilename: string); procedure AddFileEvent(const AFilename: string); public end; var Form67: TForm67; implementation {$R *.dfm} procedure TForm67.AddFileEvent(const AFilename: string); begin AddFile(AFilename); end; procedure TForm67.FormCreate(Sender: TObject); begin VST.NodeDataSize := SizeOf(TTreeData); TFileSearchTree.Create('c:\windows', AddFileEvent); end; procedure TForm67.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer); function GetIconIndex(const AFilename: string): Integer; var Icon: TIcon; FileIcon: TSHFileInfo; begin Icon := TIcon.Create; try ZeroMemory(@FileIcon, SizeOf(FileIcon)); SHGetFileInfo(PChar(AFilename), 0, FileIcon, SizeOf(FileIcon), SHGFI_SYSICONINDEX or SHGFI_ICON); Icon.Handle := FileIcon.hIcon; Result := ImageList1.AddIcon(Icon); finally Icon.Free; end; end; var TreeData: TTreeData; begin if (Kind <> ikOverlay) and (Column = 0) then begin TreeData := TTreeData(Sender.GetNodeData(Node)^); if TreeData.IconIndex < 0 then TreeData.IconIndex := GetIconIndex(TreeData.Filename); ImageIndex := TreeData.IconIndex; end; end; procedure TForm67.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); var TreeData: TTreeData; begin TreeData := TTreeData(Sender.GetNodeData(Node)^); case Column of 0: CellText := TreeData.Filename; end; end; procedure TForm67.AddFile(const AFilename: string); var NewNode: PVirtualNode; begin NewNode := VST.AddChild(nil, TTreeData.Create(AFilename)); NewNode.CheckType := ctCheckBox; NewNode.CheckState := csCheckedNormal; end; { TTreeData } constructor TTreeData.Create(const AFilename: string); begin FFilename := AFilename; FIconIndex := -1; end; { TFileSearchTree } constructor TFileSearchTree.Create(const APath: string; const AOnAddFile: TOnAddFile); begin inherited Create(False); FPath := APath; FOnAddFile := AOnAddFile; end; procedure TFileSearchTree.DoAddFile; begin FOnAddFile(FCurrentFile); end; procedure TFileSearchTree.Execute; procedure FindAllFiles(ARootFolder: string; AMask: string = '*.*'; ARecurse: Boolean = True); // von: http://www.delphipraxis.net/2235-verzeichnisse-nach-dateien-durchsuchen.html var SR: TSearchRec; begin // Implementation bis einschließlich Delphi 4 if ARootFolder = '' then Exit; if AnsiLastChar(ARootFolder)^ <> '\' then ARootFolder := ARootFolder + '\'; // Implementation ab Delphi 5 ARootFolder := IncludeTrailingPathDelimiter(ARootFolder); if FindFirst(ARootFolder + AMask, faAnyFile, SR) = 0 then try repeat if SR.Attr and faDirectory <> faDirectory then begin FCurrentFile := ARootFolder + SR.Name; Synchronize(DoAddFile); end; until FindNext(SR) <> 0; finally FindClose(SR); end; if ARecurse then if FindFirst(ARootFolder + '*.*', faAnyFile, SR) = 0 then try repeat if SR.Attr and faDirectory = faDirectory then // --> ein Verzeichnis wurde gefunden // der Verzeichnisname steht in SR.Name // der vollständige Verzeichnisname (inkl. darüberliegender Pfade) ist // ARootFolder + SR.Name if (SR.Name <> '.') and (SR.Name <> '..') then FindAllFiles(ARootFolder + SR.Name, AMask, ARecurse); until FindNext(SR) <> 0; finally FindClose(SR); end; end; begin if Assigned(FOnAddFile) then FindAllFiles(FPath, '*.*', True); end; |
AW: VirtualStringTree - Nodes hinzufügen
@ d7user1
Alles dauert seine Zeit. Das Lesen der 13000 Dateien dauert nur ein Augenblick, das Erstellen der passenden Objekte und sogar sortieren geht auch ganz schnell, selbst das Erstellen der Items. Aber kaum packst du die ListView an (vermutlich auch Virtual TreeView) um Daten anzulegen, dauert es Zeit. Das zuweisen aller Caption's ungleich "" dauert fast 1,5 Sekunden. Das Zuweisen der ImageIndex's ungleich 0 dauert etwa 2,5 Sekunden. Womit wir bei 4 Sekunden wären. Und die SubItems, selbst wenn leer, dauert auch seine Sekunden. Das bedeutet, die 13000 Dateien lesen und die gleiche Anzahl Objekte und Items anzulegen (plus sortieren) dauert nur paar Millisekunden, der Rest kostet Zeit. Ich hab gerade mein Beispiel insoweit geändert, dass zuerst alle Items angelegt werden, ohne eine Zuweisung. Der Rest wird beim Anzeigen der Items gefüllt. Also nicht wie im ersten Beispiel nur die Subitems, sondern alles. Das Ergebnis bei 13000 Dateien sind 265 Millisekunden. Ob das alles noch so seinen Sinn macht sein dahingestellt, ist einfach nur ein Test. |
AW: VirtualStringTree - Nodes hinzufügen
Zitat:
Wie der Name schon sagt ist der "Virtual Tree View" virtuell. Also es gibt da keinen direkten Zugriff auf Knoten oder Unterknoten. ItemIndex-Images werden auch nicht direkt zum Baum gespeichert, sondern "On Demand" mittels GetNodexIndex geholt. Das hat den Vorteil, dass dadurch der VST nicht an eine Struktur gebunden ist, sondern du alle möglichen Daten mit dem Baum verknüpfen und je nach Bedarf nach deinen eigenen Vorstellungen darstellen kannst. Auf einzelne Knoten (und deren Daten) kannst du somit auch nicht direkt über VST.Node[X] zugreifen, sondern müsstest erst durch den Baum iterieren. Entweder per Hand mit
Delphi-Quellcode:
, bzw.
VST.GetFirst ... while ... VST.GetNodeData ... Daten mit Suchparametern vergleichen ... end VST.GetNext
Delphi-Quellcode:
,
GetFirstSibling
Delphi-Quellcode:
, usw. Oder per
GetNextSibling
Delphi-Quellcode:
-Event und dann mit VST.IterateSubTree.
OnIncrementalSearch
|
AW: VirtualStringTree - Nodes hinzufügen
hallo, popov, fügst du die daten aus C:\Windows\System32 in deine liste hinzu? und wenn ja, ist es noch immer das beispiel aus deinem anderen thread? denn das war nicht rekursiv meine ich und es waren glaube ich etwas mehr als 2000 daten.
ich habe gerade mal geguckt. daten sammeln (C:\Windows\System32 rekursiv) und diese in records zu speichern ohne daten in der VST anzuzeigen dauert bei mir etwas mehr als 700ms. man darf nicht vergessen dass ich noch OnPaintText und OnAfterItemErase verwende und dort mit Font.Color und Brush rumgespielt wird. zu deinem beispiel jaenike: ich mache alles genau so wie du außer dass ich das nicht auf einen thread ausgelagert habe und dass ich die nodes so erzeuge:
Delphi-Quellcode:
laut dem post von Popov sind 4 sekunden also normal für das alles was ich mache?
Node := aVST.AddChild(nil);
Node.CheckType := ctCheckBox; Node.CheckState := csCheckedNormal; Data := aVST.GetNodeData(Node); Data^ := aRecord; p.s.: selbst wenn ich die Icon in der VST weglasse und die Zellentexte nicht zuweise duaert es bei mir 700ms. ich glaube der lädt die Icons und die Zellentexte von haus aus erst wenn sie gebracht werden. hier eine kleine zeitmessung für C:\Windows\System32 NICHT rekursiv: - das lesen der daten dauert bei mir ungefähr 60ms. - das erstellen der records ohne nodes zu erzeugen etwa 600ms - das erstellen der records mit nodes zu erzeugen etwa 650ms - und alles zusammen mit erstellen und freigeben der dateiliste, BeginUpdate, EndUpdate etwa 700ms. ist das so in ordnung? großes edit: ich weiß jetzt warum das 4 sekunden dauert. beim erstellen meiner records nutze ich einmal IntToStr(getFileSizeA()) und einmal DateTimeToStr(getFileLastModified()). ohne IntToStr(getFileSizeA()) dauert es nur 1.5 sekunden und ohne DateTimeToStr(getFileLastModified()) dauert es nur 3.3 sekunden. ohne beides dauert alles zusammen plus anzeigen der 13.000 dateien 400ms. meine zwei funktionen sehen so aus:
Delphi-Quellcode:
function getFileSizeA(const FileName: string): Int64;
var SR: TSearchRec; begin Result := 0; if not FileExists(FileName) then Exit; if FindFirst(FileName, faAnyFile and not faDirectory, SR) = 0 then try Result := SR.Size; finally SysUtils.FindClose(SR) end; end; function getFileLastModified(const FileName: string): TDateTime; var SR: TSearchRec; SystemTime: TSystemTime; NewWriteTime: TFileTime; begin Result := 0; if FindFirst(FileName, faAnyFile, SR) = 0 then try if (Windows.FileTimeToLocalFiletime(SR.FindData.ftLastWriteTime, NewWriteTime) and Windows.FileTimeToSystemTime(NewWriteTime, SystemTime)) then Result := Encodedate(SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay) + Encodetime(SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, SystemTime.wMilliseconds); finally SysUtils.FindClose(SR) end; end; |
AW: VirtualStringTree - Nodes hinzufügen
Wobei das Zeichnen usw. egal ist, da das ja nur die tatsächlich angezeigten Knoten betrifft.
Was bei dir aber noch fehlt ist ein BeginUpdate...EndUpdate, denn dadurch dauert das Hinzufügen der Knoten sehr viel länger. Wenn man den Thread noch ändert und die Dateien häppchenweise statt einzeln übergibt plus BeginUpdate...EndUpdate sollte das ganze quasi sofort initial angezeigt werden (und dann natürlich noch kurz nachladen). Der übliche Weg sieht übrigens so aus, dass man immer nur die Dateien der aktuellen Ebene anzeigt und beim Aufklappen die Ebene darunter einliest. So sollte es keinerlei Verzögerungen geben, es sei denn du hast Verzeichnisse mit enorm vielen Dateien. |
AW: VirtualStringTree - Nodes hinzufügen
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Und ja, es ist nicht rekursiv, denn es sollte nur ein Ordner gelesen werden. Ich denke mir aber, dass es keinen besonderen Unterschied macht wenn man den gesamten Inhalt liest, inkl. Unterordner. Trotzdem, auch wenn ich das so hin gekriegt habe, es ist eher nur just4fun. Ich hab noch nie mit virtuellem ListView gearbeitet, evtl. ist es für die Aufgabe besser geeignet. Was das Andere angeht, Total Commander hatte bis (mindestens) Version 5.5 die Möglichkeit einen Verzeichnis-Baum auszugeben. Um das zu laden hat er zum Schluss fast immer eine Minute gebraucht. Aber man läd nun mal nicht alles auf einmal, vor allem bei TreeView. Das dauert zu lange. |
AW: VirtualStringTree - Nodes hinzufügen
Zitat:
FindFirst sucht ja bereits nach dem Namen der Datei, findet es nicht, geht sie nicht in der Block rein (hier try finally), sondern übergeht ihn. Somit kann man sich die FileExists Abfrage sparen, sie kostet nur Zeit. SR.Size gibt u. U. die falsche Dateigröße zurück, denn es ist Integer. Solange du unter 2 GByte bleibst, merkst du nichts. Die richtige Größe steckt in FindData. Hier die Formel:
Delphi-Quellcode:
Ansonsten wird hier jede Datei anscheinend zwei mal angepackt - zuerst um den Namen zu lesen, später noch mal um die Größe zu erfahren. Dabei enthält TSearchRec schon beim ersten Zugriff alle Infos.
x := Int64(SR.FindData.nFileSizeLow) or (Int64(SR.FindData.nFileSizeHigh) shl 32);
// |
AW: VirtualStringTree - Nodes hinzufügen
Zitat:
Heute ist es ein Int64 Wert. |
AW: VirtualStringTree - Nodes hinzufügen
Gibt SR.Size (bei aktuellen Delphis) auch den korrekten Wert an (> 2GB)?
|
AW: VirtualStringTree - Nodes hinzufügen
@d7user1
Weil es mich interessierte, habe ich die 13000 Daten in ListView eingelesen, wobei ich das LV virtuell nutzte. Ist alles in 31 ms erledigt (inkl. lesen, sortieren, usw). |
AW: VirtualStringTree - Nodes hinzufügen
hallo. genau das habe ich gestern auch einmal getan. die zeit weiß ich nicht mehr aber es war sehr schell. schneller als der VirtualStringTree.
das einzige was mich störte ist dass ich checkboxen gebraucht habe, ich die aber selbst nicht zeichnen kann. und ich bin sicher genau da, beim zeichnen der checkboxen, wird die listview wieder sehr langsam. mein code ist momentan so weit angepasst dass das einlesen von 13000 dateien + diverses zeichnen von bestimmten nodes + dateigrößenbestimmung und datumsumwandung in etwa 450ms erledigt ist. dabei erledige ich das bestimmen der dateigröße und das umwandeln des dateidatums im OnGetText-Event statt wie zuvor beim erstellen der nodes. beim erstellen der nodes dauert es 4 sekunden. kleiner vergleich: dasselbe mit einer listview + checkboxen dauert etwa 25 sekunden. |
AW: VirtualStringTree - Nodes hinzufügen
Wie schon gesagt, Du könntest Dir auch mal das NextGrid anschauen, das ist IMO etwas einfacher zu handhaben als der VST. Die Versionen für Delphi 6 und 7 sind Freeware.
|
AW: VirtualStringTree - Nodes hinzufügen
@d7user1
Ok, das ist u. U. mit etwas Arbeit verbunden, da die CheeckBoxes tatsächlich nicht gezeichnet werden. Aber das stellt sich die Frage was schneller ist - sich die Kenntnisse über eine neue Komponente aneignen oder CheckBoxen selber zeichnen. Das Zeichnen selbst sollte kein großes Problem sein:
Delphi-Quellcode:
In ImageList2 sind zwei 16x16 große Bitmaps mit, die für CheckBox An/Aus stehen. Den Rest, wie auch Checkbox Klick, muss man noch machen. Ist aber alles machbar.
var
DispRect : TRect; begin DispRect := Item.DisplayRect(drIcon); with Sender as TListView do if Item.Checked then ImageList2.Draw(Canvas, DispRect.Left - 16, DispRect.Top, 1) else ImageList2.Draw(Canvas, DispRect.Left - 16, DispRect.Top, 0); end; |
AW: VirtualStringTree - Nodes hinzufügen
ich würde schon gerne weiter die listview benutzen. aber das mit dem bitmap zeichnen usw, ich habe es gerade ausprobiert, das ist mir ein wenig zu wackelig.
es gäbe sogar noch einen grund bei der listview zu bleiben: wenn mein VirtualTreeView nicht genug nodes hat um dem scrollbalken anzuzeigen, dann bekommen meine nodes keine hintergdunfarbe (Brush). ein manuelles VST.Refresh zeigt mir die farben an. aber ich habe keine ahnung wo ich diesen refresh hinsetzen muss. edit: ich habe jetzt mal in GetImageIndex ein VST.Invalidate; gesetzt. das scheint zu funktionieren aber ob es schön ist weiß ich nicht. damit es nicht ständig aufgerufen wird und somit prozessorzeit unnötig für nichts beansprucht wird eine boolsche variable gesetzt wenn es aufgerufen wurde. |
AW: VirtualStringTree - Nodes hinzufügen
Also bisher habe ich noch nicht mit Virtual ListView gearbeitet, ist im Grunde aber eine feine Sache, man muss nur die Daten auslagern. Das mit den Checkboxen ist Pech, da muss man eben selbst programmieren.
NextGrid und VST sehen verdammt gut aus, müssen aber installiert werden. Vorausgesetzt also Virtual ListView ist nichts, auch NextGrid und VST nicht, eben aus den genannten Gründen, stellt sich die Frage nach dem Beispiel im Beitrag #17. Das ist kein Virtual ListView, arbeitet aber insoweit ähnlich, als das es zuerst komplett leer ist und erst beim Scrollen gefüllt wird. Es ist etwas langsamer, hat dafür aber CheckBoxen, da es eine normale ListView ist. Sollte also die Lösung für dein Problem sein. |
AW: VirtualStringTree - Nodes hinzufügen
ich werde mir dein beispiel mal ansehen und mit meinem VST vergleichen.
meine "Dateien-lesen-funktion" braucht momentan für das lesen von C:\Windows rekursiv 6 sekunden. (95000 dateien) die grafische darstellung dauert nur wenige millisekunden. |
AW: VirtualStringTree - Nodes hinzufügen
Nun, da ist nichts besonderes dran, bis auf, dass zuerst nur leere Items angelegt werden. Diese werden später JustInTime gefüllt.
|
AW: VirtualStringTree - Nodes hinzufügen
demnach sind 6 sekunden für ein verzeichnis wie C:\windows normal?
|
AW: VirtualStringTree - Nodes hinzufügen
Also ich weiß nicht wie du auf die 6 Sekunden kommst. Ich hab gerade den Code geändert und ihn auch Unterverzeichnisse einbinden lassen. Dauer bei knapp 12000 Dateien im Windowsordner etwa 500 ms (komplett, einlesen und in LV ausgeben).
|
AW: VirtualStringTree - Nodes hinzufügen
mist. ich probiere gleich mal die funktion hier aus der code-lib aus wenn ich die noch finde.
edit: ok also selbst mit dieser funktion dauert es 4 bis 5 sekunden: ![]() kann es sein dass du eine SSD hast? |
AW: VirtualStringTree - Nodes hinzufügen
Delphi-Quellcode:
procedure GetFilesOL(SearchPath: String; ObjectList: TObjectList; SubFolder: Boolean);
var SearchRec: TSearchRec; FileInfo: TFileInfoEx2; begin SearchPath := IncludeTrailingPathDelimiter(SearchPath); if FindFirst(SearchPath + '*.*', faAnyFile or faDirectory, SearchRec) = 0 then try repeat if (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then with ObjectList do begin FileInfo := TFileInfoEx2.Create; Add(FileInfo); FileInfo.Path := SearchPath; FileInfo.Name := SearchRec.Name; FileInfo.SearchRec := SearchRec; end; until FindNext(SearchRec) <> 0; finally FindClose(SearchRec); end; //---------------------------------------------------------------------------- if SubFolder then begin if FindFirst(SearchPath + '*.*', faDirectory, SearchRec) = 0 then try repeat if ((SearchRec.Attr and faDirectory) = faDirectory) and (SearchRec.Name <> '.') and (SearchRec.Name <> '..') then GetFilesOL(SearchPath + SearchRec.Name, ObjectList, SubFolder); until FindNext(SearchRec) <> 0; finally FindClose(SearchRec); end; end; end; |
AW: VirtualStringTree - Nodes hinzufügen
jop. also mit deiner prozedur mit stringlist anstatt objektlist dauert es dennoch 4 sekunden.
entweder ist es die stringlist oder es ist weil ich keine ssd habe. es ist zudem eine angepasste version der datensammlung mit dingen die ich benötige. das würden die 2sekunden überlänge erklären |
AW: VirtualStringTree - Nodes hinzufügen
Liste der Anhänge anzeigen (Anzahl: 1)
Vielleicht hast du einfach nur einen langsamen Rechner.
Teste das mal: (siehe Anhang) PS: die Sortierung ist noch nicht angepasst und sortiert nur nach Daten, ohne Pfade zu berücksichtigen. |
AW: VirtualStringTree - Nodes hinzufügen
mh. intel core i7 mit 4* 1.6ghz
ram weiß ich grade nicht aber der ist schon schnell. 1333mhz glaube ich pro block und eine hybridfestplatte. dein beispiel läuft bei mir in 7-8 5-6 sekunden durch. ich hatte mal beobachtet dass mein rechner langsmer wird wenn man ZU OFT ohne einen neustart mit delphi kompiliert. vielleicht ist es das. |
AW: VirtualStringTree - Nodes hinzufügen
Alter AMD Athlon 7750 Dual-Core Prozessor, 2.70 GHz, und trotzdem schneller :P
EDIT: Damit du siehst, dass die 500 ms stimmen: ![]() Wenn du wirklich 5 Sekunden bei gleichem Code brauchst, dann stimmt da was nicht. Teste mal den Speed deiner Festplatte damit: ![]() |
AW: VirtualStringTree - Nodes hinzufügen
selbst nach einem neustart keine wirkliche besserung. mein beispiel lief vorher in 6.X sekunden durch nun in 5.X.
vielleicht ist meine windows-installation hinüber? dass ich das mit einer testversion von XE2 kompiliere ändert nichts oder? |
AW: VirtualStringTree - Nodes hinzufügen
Liste der Anhänge anzeigen (Anzahl: 1)
das sieht dann so aus:
![]() oder so: ![]() wielange braucht mein berispiel denn bei dir? (anhang) |
AW: VirtualStringTree - Nodes hinzufügen
Sieht ok aus, obwohl 1GB etwas wenig sind. Wiederhole das für dich mal mit 40 GB.
Ich weiß zurzeit auch nicht wo das Problem liegt. |
AW: VirtualStringTree - Nodes hinzufügen
kann es sein dass das daran liegt dass es ein laptop ist?
könntest du mein beispiel oben eventuell testen? edit: ich habe mal die dateiliste der dateien die rekursiv in C:\Windows sind in eine textdatei gepackt. mein testprogramm lädt nun diese testdatei anstatt die liste selber zusammenzustellen per FindFirst usw usw. mit dem code aus der code-lib braucht mein rechner 4 bis 5 sekunden. mein angepasster, für meine bedürfnisse, code braucht etwa 5.5 bis 6 sekunden. und das laden der textdatei direkt in die stringlist benötigt nur 200ms ungefähr. demnach ist es eindeutig meine festplatte die entweder hinüber ist oder meine windows-installation. das seltsame ist aber dass ein anderer datenträger bei 13000 dateien dennoch 3 sekunden benötigt. ich glaube also es ist die windows-installation. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:30 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz