Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen (https://www.delphipraxis.net/206324-virtualstringtree-shgetfileinfo-haengt-programm-auf-canvas-erlaubt-kein-zeichnen.html)

DieDolly 9. Dez 2020 17:45


VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen
 
Ich fülle ein VST ganz normal über Init, GetText, Free. So wie es ja sein soll. Das macht auch keine Probleme.

Im Event GetImageIndex macht diese Zeile hier Probleme, wenn ich öfter schnell rauf- und runterscrolle und danach irgendeine der Spaltenbreiten verändere.
Ein paar mal verändern geht, aber sobald ich auf einen Trenner doppelklicke, sodass sich die Spalte eigentlich die Auto-Größe holt, hängt sich alles auf.
Das Programm hängt sich auf und manchmal kommt die Fehlermeldung oben. Manchmal kommt auch Falscher Parameter. Manchmal kommt das auch, wenn ich das Fenster über längere Zeit offen lasse ohne irgendwas zu machen. Manchmal reicht auch schon rumscrollen.
Delphi-Quellcode:
if SHGetFileInfo(PChar(FileName), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX or SHGFI_ICON or
SHGFI_SMALLICON) = 0 then
Lasse ich die Zeile weg, habe ich gar keine Probleme. Mache ich irgendwas falsch

(wie ich Icons lade und anzeige, sieht man hier https://www.delphipraxis.net/1478875-post14.html)

DieDolly 10. Dez 2020 12:10

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Keiner eine Idee was hier an VirtualStringTree falsch sein kann? Wenn ich keine Icons anzeige ist das Problem nicht da.

Gausi 10. Dez 2020 12:32

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Ohne den Rest deines Programms zu kennen:

Das riecht verdächtig nach Threads. Bearbeitest du irgendwo außerhalb des VCL-Mainthreads Bitmaps? Denn da muss man höllisch aufpassen, bzw. es besser ganz sein lassen. Selbst Thread-lokale TBitmaps können dir den Rest des Programms an ganz anderer Stelle zerschießen.

DieDolly 10. Dez 2020 13:12

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Arbeitet VirtualStringTree intern mit Threads?
Weil ich selber nicht an dieser Stelle. Mit Bitmaps mache ich auch nichts.

Wenn das VST 10000 Einträge hat, jeder Eintrag 6 Spalten und jeweils 2 Icons und man richtig wild rauf und runter fährt, kommt es auch irgendwann zu dem Fehler.
Definitiv kommt es aber zu dem Fehler, wenn man auf einen Spalten-Trenner doppel-klickt, damit die Spalte die Auto-Breite bekommt. Dann kommt auch irgendwann Systemresourcen erschöpft und Canvas erlaubt kein Zeichnen.

FormCreate
Delphi-Quellcode:
 SmallImages := TImageList.Create(Self);
 SystemImageList := SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON);

 SmallImages.Handle := SystemImageList;
 SmallImages.ShareImages := True;
 VST.Images := SmallImages;
Und dann, egal wo, ob im GetImageIndex oder InitNode oder wo auch immer, sobald ich mit SHGetFileInfo arbeite um an die Icons zu kommen, kommen die Probleme.
Die Icons werden alle angezeigt, das ist kein Problem. Aber wild rumscrollen und sowas erzeugt dann irgendwann einfach ein einfrierendes/schwarzes Fenster.

Dalai 10. Dez 2020 15:00

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Zerstörst du denn die Icons irgendwann wieder? Die Remarks zu MSDN-Library durchsuchenSHGetFileInfo sagen klar, dass man DestroyIcon rufen muss, wenn man die Ressourcen nicht mehr braucht:
Zitat:

If SHGetFileInfo returns an icon handle in the hIcon member of the SHFILEINFO structure pointed to by psfi, you are responsible for freeing it with DestroyIcon when you no longer need it.
Außerdem:
Zitat:

You must initialize Component Object Model (COM) with CoInitialize or OleInitialize prior to calling SHGetFileInfo.
Grüße
Dalai

DieDolly 10. Dez 2020 15:18

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Reicht es, wenn ich die Imagelist einfach leere wenn ich das Fenster schließe?
Kannst du mir dafür ein Beispiele geben, wie ich das mit CoInitialize richtig mach?

Einen Fehler hab ich vergessen. "Falscher Parameter" aus der Vcl.Graphics kommt auch gelegentlich. Wie gesagt bei wildem umherscrollen.
Ich dachte immer ein VirtualStringTree hat kein Problem mit Millionen Einträgen. Bei mir sind es schon 9000 die Probleme machen (nur mit Icons, alles andere ist feinst säuberlich generisch aufgebaut).

venice2 10. Dez 2020 15:33

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Zitat:

wenn man die Ressourcen nicht mehr braucht:
yep und das ist der Fall wenn sie zu einer Image-list addiert wurden.
Die Image-list verwaltet dann die Icons das Handle des Icon das du vorher addiert hast musst du dann löschen.

Zitat:

Kannst du mir dafür ein Beispiele geben, wie ich das mit CoInitialize richtig mach?
Was für ein Beispiel?

wenn du sonst nirgends ein COM object verwendest.
Dann rufe vor SHGetFileInfo CoInitialize auf und wenn du alle Icons addiert hast CoUnInitialize.

DieDolly 10. Dez 2020 15:37

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Ich rufe SHGetFileInfo in InitNode auf. Das heißt es wird nur ein Icon geladen, wenn es benötigt wird. Ich dachte eigentlich immer, dass das helfen würde.
CoInitialize und CoUnInitialize um SHGetFileInfo hat hier nichts gebracht leider.

Könnte es helfen, wenn ich SHGetFileInfo ganz aus der Unit mit dem VST auslagere und schon dort aufrufe, wo ich meine Liste für das VST erestelle?
Im VST GetImageIndex hole ich mir dann nur noch den ImageIndex.

venice2 10. Dez 2020 15:39

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Zitat:

Zitat von DieDolly (Beitrag 1478865)
Ich rufe SHGetFileInfo in InitNode auf. Das heißt es wird nur ein Icon geladen, wenn es benötigt wird. Ich dachte eigentlich immer, dass das helfen würde.
CoInitialize und CoUnInitialize um SHGetFileInfo hat hier nichts gebracht leider.

Fülle die ImageList mit allen Icons und hole dir dann den Index aus der ImageList vom Icon das du benötigst für die jeweilige Node.
Dafür ist sie da!
Ich mache hier auch nichts anderes.

Delphi-Quellcode:
  if hLarge = 0 then
  begin
    hLarge := ImageList_Create(round(bw), round(bh), ILC_COLOR32, 1, 1); // 32 Bit Bitmap konvertiert zu Icon
    ListView_SetImageList(Handle, hLarge, LVSIL_NORMAL);
  end;
  // Icon zur Liste addieren
  ImageList_AddIcon(hLarge, hIconItem);

  SetLength(ItemsInfo, nItem + 1);
  ItemsInfo[nItem].Item := nItem;
  ItemsInfo[nItem].SubItem := nSubItem;
  ItemsInfo[nItem].Width := round(bw);
  ItemsInfo[nItem].Height := round(bh);
  ItemsInfo[nItem].ImgIcon := hIconItem;
  ItemsInfo[nItem].IdentStr := ImgIdent;

  // Icon freigeben
  // wird nicht mehr verwendet da in der ImageList enthalten
  DestroyIcon(hIconItem);
Ok ist für ein ListView und Win32 Api aber in der Funktionsweise das gleiche.
Wenn ich jedes Icon extra laden würde oh.. oh.. das wird nix.

Image list erstellen
Icon addieren
Handle löschen.

DieDolly 10. Dez 2020 15:49

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Deinen Code verstehe ich nicht. Ich mache nichts anderes. Ich lade das Icon und weise den ImageIndex zu.
Ich habe den Code jetzt ausgelagert und komplett von der VST-Unit abgekoppelt. Trotzdem kommen Fehlermeldungen. Bis vor 10.3.3 war das alles gar kein Problem bin ich der Meinung.

Mein Code ist wie gesagt so.
Delphi-Quellcode:
 SmallImages := TImageList.Create(Self);
 SystemImageList := SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON);

 SmallImages.Handle := SystemImageList;
 SmallImages.ShareImages := True;
 VST.Images := SmallImages;
SmallImages und SystemImageList: passiert im FormCreate. Beides lokale Variablen in FormCreate (warum, keine Ahnung).

venice2 10. Dez 2020 15:56

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Zitat:

Zitat von DieDolly (Beitrag 1478869)
Deinen Code verstehe ich nicht. Ich mache nichts anderes. Ich lade das Icon und weise den ImageIndex zu.
Ich habe den Code jetzt ausgelagert und komplett von der VST-Unit abgekoppelt. Trotzdem kommen Fehlermeldungen. Bis vor 10.3.3 war das alles gar kein Problem bin ich der Meinung.

Du musst alle in das Imagelist addieren die du benötigst sonst löst du jedesmal beim addieren eines neuen Icon ein repaint aus.
Das ist sehr un-konstruktiv jedesmal eine neue ImageListe zu erstellen für 1 Icon! sorry
Einmalig und fertig.

Das ist dein Problem.
Und wie gesagt das Handle des Icon löschen.

Delphi-Quellcode:
DestroyIcon(Info.HIcon);

DieDolly 10. Dez 2020 16:00

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Ungefähr so?

FormCreate
Delphi-Quellcode:
 SmallImages := TImageList.Create(Self);
 SystemImageList := SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON);

 SmallImages.Handle := SystemImageList;
 SmallImages.ShareImages := True;
 VST.Images := SmallImages;
InitNode
Delphi-Quellcode:
 SHGetFileInfo(PChar(FileName), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON);
 ImageList_AddIcon(SmallImages.Handle, Info.iIcon);
 DestroyIcon(Info.iIcon); // Mit dieser Zeile sehe ich dann keine Icons
Ach das funktioniert doch eh nicht. Deinen Code verstehe ich nicht und auch keine Ahnung wo der hin soll, welche Variablentypen das sind, wie ich das am Ende anzeige usw.

venice2 10. Dez 2020 16:07

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Zitat:

Zitat von DieDolly (Beitrag 1478873)
Ungefähr so?

FormCreate
Delphi-Quellcode:
 SmallImages := TImageList.Create(Self);
 SystemImageList := SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON);

 SmallImages.Handle := SystemImageList;
 SmallImages.ShareImages := True;
 VST.Images := SmallImages;
InitNode
Delphi-Quellcode:
 SHGetFileInfo(PChar(FileName), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON);
 ImageList_AddIcon(SmallImages.Handle, Info.iIcon);
 DestroyIcon(Info.iIcon); // Mit dieser Zeile sehe ich dann keine Icons
Ach das funktioniert doch eh nicht. Deinen Code verstehe ich nicht und auch keine Ahnung wo der hin soll, welche Variablentypen das sind, wie ich das am Ende anzeige usw.

sorry dann läuft bei dir was falsch.
Das ImageList wird zerstört oder sonst was.
Ist aber auch möglich das es in 10.4 einfach nicht mehr korrekt funktioniert.

DieDolly 10. Dez 2020 16:08

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Ich verstehe deine Aussage aber auch nicht
Zitat:

Das ist sehr un-konstruktiv jedesmal eine neue ImageListe zu erstellen für 1 Icon! sorry
Das mache ich doch gar nicht.

Und außerdem. Woher will das VST wissen, welchen Index es für welches Node braucht? Dafür muss ich doch zwangsweise in jedem Node 1x GetSHFileInfo aufrufen.

Zitat:

Das ImageList wird zerstört oder sonst was.
Ich zerstöre da nix. Diese komischen Probleme kommen erst bei mehreren Tausend Einträgen.

Hier nochjmal zusammengefasst wie ich es immer gemacht habe und wie es auch eigentlich immer funktioniert hat

FormCreate
Delphi-Quellcode:
 SmallImages := TImageList.Create(Self);
 SystemImageList := SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON);

 SmallImages.Handle := SystemImageList;
 SmallImages.ShareImages := True;
 VST.Images := SmallImages;
InitNode
Delphi-Quellcode:
 SHGetFileInfo(PChar(FileName), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON);
 MeinNode-generisch.MeinIconIndex := Info.iIcon; // jetzt weiß der Datensatz unter dem Node, welcher IconIndex das Icon braucht.
VSTGetImageIndex
Delphi-Quellcode:
 if Kind in [ikNormal, ikSelected] then
  ImageIndex := MeinNode-generisch.MeinIconIndex;
ich glaube die ImageList benutze ich nicht einmal.

venice2 10. Dez 2020 16:21

AW: SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen / VirtualStringTr
 
Zitat:

Das mache ich doch gar nicht.
Ich habe es so verstanden.
Zitat:

Ich rufe SHGetFileInfo in InitNode auf. Das heißt es wird nur ein Icon geladen
Delphi-Quellcode:
 SHGetFileInfo(PChar(FileName), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON);
 MeinNode-generisch.MeinIconIndex := Info.iIcon; // jetzt weiß der Datensatz unter dem Node, welcher IconIndex das Icon braucht.
Zitat:

ich glaube die ImageList benutze ich nicht einmal.
jetzt weiß der Datensatz unter dem Node, welcher IconIndex das Icon braucht.
Das ist kein Index aus der ImageList sondern dein HIcon.
Und du lädst jedesmal ein neues Icon anstatt die ImageListe zu verwenden wo dann alle schon enthalten sind.


da ist so einiges faul.

Der richtige weg ist.
Die ImageList einmalig mit allen Icons zu füllen.
Und bei InitNode den entsprechenden index aus der ImageList (Hicon) der Node zuzuweisen.

DieDolly 10. Dez 2020 16:25

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Wieso "so einiges"?
Ich würde es ja verbessern aber ich verstehe deinen Code nicht, weil da für mich der Kontext fehlt.
Ich habe das eben aber mal mit der ImageList versucht. Egal ob ein Icon schon da drin ist oder nicht, es werden in InitNode immer weiter Icons in die Liste gepackt.
Ich kapiere mittlerweile überhaupt nix mehr und besonders nicht, warum die ImageList angeblich so gut sein soll. Woher soll die denn beim Hinzufügen neuer Icons wissen, ob das schon da drin ist oder nicht? Und auch wenn, das ist ja nicht einmal mein Problem. ich muss für JEDEN Node GetSHFileInfo aufrufen, um überhaupt herauszubekommen, welches Icon dahintersteckt. Wie soll mir da eine ImageList helfen?

Du redest hier im Prinzip mit einem Anfänger!

Hast du keinen normalen Code statt den aufd Seite 1 mit SetLength, ItemsInfo und so?

venice2 10. Dez 2020 16:29

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Zitat von DieDolly (Beitrag 1478878)
Wieso "so einiges"?
Ich würde es ja verbessern aber ich verstehe deinen Code nicht, weil da für mich der Kontext fehlt.
Ich habe das eben aber mal mit der ImageList versucht. Egal ob ein Icon schon da drin ist oder nicht, es werden in InitNode immer weiter Icons in die Liste gepackt.
Ich kapiere mittlerweile überhaupt nix mehr und besonders nicht, warum die ImageList angeblich so gut sein soll. Woher soll die denn beim Hinzufügen neuer Icons wissen, ob das schon da drin ist oder nicht? Und auch wenn, das ist ja nicht einmal mein Problem. ich muss für JEDEN Node GetSHFileInfo aufrufen, um überhaupt herauszubekommen, welches Icon dahintersteckt. Wie soll mir da eine ImageList helfen?

Du redest hier im Prinzip mit einem Anfänger!

Hast du keinen normalen Code statt den aufd Seite 1 mit SetLength, ItemsInfo und so?

so ist eine ImageList aufgebaut..
Nur zur Veranschaulichung es geht um die Bilder..

https://www.freetutes.com/learn-vb6-...esson4/p3.html

DieDolly 10. Dez 2020 16:34

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Verstehe ich alles nicht. Ich habe es im Prinzip so gemacht wie hier aus #7
https://www.delphipraxis.net/611374-post7.html

venice2 10. Dez 2020 16:42

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Nun ja du rufst in jeder InitNode SHGetFileInfo auf das ist ein Overhead oder?
Warum? Frage ich mich.
Das meine ich mit Un-Konstruktiv.

https://www.youtube.com/watch?v=2fb2Ex1Pxmk

DieDolly 10. Dez 2020 16:42

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Dazu meine Gegenfrage
Zitat:

Und wenn ich nicht einmal GetSHFileInfo für jeden Node aufrufen darf, verstehe ich auch nicht, wie ich sonst an das Icon kommen soll.
Hier in #7 wird es ja auch in jeden GetImageIndex aufgerufen und scheinbar funktioniert es.
https://www.delphipraxis.net/611374-post7.html

Oder ist das alles schon wieder so ein unbekannter Delphi-Fehler?

Hier ist auch ein Beispiel wo SHGetFileInfo ständig aufgerufen wird ohne irgendwas mit Destroy oder so
https://www.delphipraxis.net/1099656-post4.html

venice2 10. Dez 2020 17:05

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Ich würde dir vorschlagen dir die Samples vom VirtualStringTree anzuschauen.
https://github.com/JAM-Software/Virtual-TreeView
Keine Ahnung ob es das gleiche ist was du verwendest.

Zuletzt.
https://stackoverflow.com/questions/...ngetimageindex
https://stackoverrun.com/de/q/3265058

den index aus der ImageList bekommt man so.
VirtualStringTree1GetImageIndex

Bei Google suchenvirtualstringtree and imagelist delphi

EDIT:
Zitat:

Hier ist auch ein Beispiel wo SHGetFileInfo ständig aufgerufen wird ohne irgendwas mit Destroy oder so
Dann darfst du dich nicht wundern das nichts mehr gezeichnet wird.
Delphi-Quellcode:
ImageIndex := MeinNode-generisch.MeinIconIndex;

Du lädst jedesmal ein neues Icon.
Prüfe dann mal das Handle es ist unterschiedlich oder?
Also wird das Icon nicht freigegeben das bedeutet der Speicher deiner Anwendung explodiert Exponential
Das ist der Grund warum du dann irgendwann einfach nicht mehr zeichnen kannst.

Das du das Icon nicht mehr siehst ist normal nach DestroyIcon(Info.Hicon) denn du verwendest nicht den Index der ImageList sondern dein Index ist ein HIcon.
Das ist definitiv falsch!

DieDolly 10. Dez 2020 17:27

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

den index aus der ImageList bekommt man so.
VirtualStringTree1GetImageIndex
Also ich habe keine Ahnung wie man damit den ImageIndex aus der ImageList bekommen.

Alle deine Links kenne ich leider schon.

venice2 10. Dez 2020 17:33

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Zitat von DieDolly (Beitrag 1478890)
Zitat:

den index aus der ImageList bekommt man so.
VirtualStringTree1GetImageIndex
Also ich habe keine Ahnung wie man damit den ImageIndex aus der ImageList bekommen.

Alle deine Links kenne ich leider schon.
Die Demos helfen leider nicht weiter, weil da überall nur feste IconIndexes zugewiesen werden und nichts vom System geladen wird.

Lese mein Edit.

Das einzige was noch helfen könnte prüfe ob sich das Handle des Icon zu dem vorherigen unterscheidet
und lösche das alte (HIcon) bevor du ein neues lädst.

DieDolly 10. Dez 2020 17:35

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Hier ist auch ein Beispiel wo SHGetFileInfo ständig aufgerufen wird ohne irgendwas mit Destroy oder so
Dann darfst du dich nicht wundern das nichts mehr gezeichnet wird.
Eben dann wird doch alles gezeichnet. Das ist jetzt aber egal.

Zitat:

Das ist der Grund warum du dann irgendwann einfach nicht mehr zeichnen kannst.

Das du das Icon nicht mehr siehst ist normal nach DestroyIcon(Info.Hicon) denn du verwendest nicht den Index der ImageList sondern dein Index ist ein HIcon.
Das ist definitiv falsch!
Ich verstehe gar nichts mehr.
Im InitNode rufe ich 1x SHGetFileInfo auf. Und egal, ob ich da jetzt mit einer ImageList was mache, mit Destroy oder ohne: die Fehler kommen trotzdem.

Jumpy 10. Dez 2020 17:38

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Wenn du jedes mal vom System lädst, was soll die ImageList?

Sonst müsstest du einmal beim Befüllen des VST bei jedem Node einmalig gucken welches Image mit welchem Index das in der ImageList ist und das dann in dem Node speichern.

venice2 10. Dez 2020 17:39

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Ich verstehe gar nichts mehr! Jetzt ist Destroy falsch?
Ja.

Weil du das zuletzt geladenen Icon freigibst und nicht das vorherige das geladen wurde.
Du erkennst den unterschied?
Prüfe doch einfach mal was für einen Speicher deine Anwendung verwendet und vor allem ob dieser freigegeben wird. (Taskmanager)

Zitat:

Wenn du jedes mal vom System lädst, was soll die ImageList?
Nun das schliesst aber nicht aus das die Handles der vorherigen geladenen Icons nicht freigegeben werden.
Das ist nun mal fakt.

Die frage ist doch was geladen wird.
Wenn es nur um System icons geht wie Folder ec.. dann ist eine Imagelist immer vom vorteil.
Denn diese ändern sich nicht.

Aber dafür gibt es ja schon eine liste "SystemImageList"

Zitat:

VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichnen
Aber gut die Frage ist mit einem Satz beantwortet.
Gebe die Icon Handles frei und alles ist gut.

venice2 10. Dez 2020 18:06

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Eine Idee hätte ich noch.
Nur zum testen ob dein Problem damit behoben ist.

Erstelle eine ImageList.
Add 1 Icon nach dem addieren lösche das Handle.
Dann übergeben jeder Node den Index 0 der ImageList.

Prüfe dann ob dein Problem behoben ist.
Ja jede Node hat dann das gleiche Icon. Ist auch nur zum testen gedacht ob dein Problem damit behoben ist.
Falls ja dann weist du woran es liegt.

DieDolly 10. Dez 2020 18:10

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Sorry wegen der langen Antwortzeit. Ich hatte hier Probleme die Datei hochzuladen.

Ich habe hier mal ein Minimalprojekt gebaut. Das zeigt das Problem und auch GANZ grob runtergebrochen meinen Aufbau mit meiner Liste.
Ich glaube hier dran kann man am besten sehen was das Problem ist.

Benötigt wird ein Verzeichnis mit sehr vielen Dateien und Verzeichnissen. Ich nehme dafür gerne das Mozilla-Verzeichnis in AppData.
Die Datei ist etwas größer weil ich da noch die Exe-Datei drin habe, kompiliert mit 10.3.3 CE und VirtualStringTree 7.X (die neueste).

... Dateien hochladen funktioniert heute nicht. Deswegen hab ichs woanders hochgeladen: https://www.file-upload.net/download...15/VST.7z.html

Dalai 10. Dez 2020 20:49

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Ist das denn richtig?
Delphi-Quellcode:
    if SHGetFileInfo(PChar(TreeDataKlassen[Node^.Index].PfadSpalte1), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON) = 0 then
    begin
     ImageIndex := TreeDataKlassen[Node^.Index].IconIndexSpalte1;
     // Eigentlich müsste das Icon angezeigt werden, wird es aber nicht.
    end;
Wird .IconIndexSpalte1 jemals gesetzt und wenn ja, wo?

Übrigens:
Delphi-Quellcode:
procedure AddAllFilesInDir(const Dir: string; var List: TStringList);
List sollte
Delphi-Quellcode:
const
sein, nicht
Delphi-Quellcode:
var
, denn es soll ja nicht der Zeiger zur Liste geändert werden (können) sondern nur deren Inhalt.

Grüße
Dalai

DieDolly 10. Dez 2020 21:02

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Der Code da ist unwichtig, ist ein Fehler beim Kopieren passiert.
Es funktioniert ja ohnehin nicht, egal was ich mache und ob da jetzt eine Zuweisung fehlt.

Ich habe dieses Minimalbeispiel nur gebaut um grob zu zeigen wie alles aufgebaut ist. Und in der Hoffnung, dass ihr mir helfen könnt, SHGetFileInfo() dort richtig einzubauen.

So bekomme ich was angezeigt aber es ruckelt, zuckelt und führt sicher wieder zu Fehlern.
Was ich gerade bestätigen konnte: ein Doppelklick auf den Trenner nach Spalte 1 führt zum Einfrieren und OutOfResources; aus Vcl.Graphics wird aufgerufen.
Delphi-Quellcode:
procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex);
var
 Info: TSHFileInfo;
begin
 if (not(Column in [0, 1])) or (not Assigned(TreeDataKlassen)) then
  Exit;

 if Kind in [ikNormal, ikSelected] then
  begin
   if TreeDataKlassen[Node^.Index].IconIndexSpalte1 = -1 then
    begin
      SHGetFileInfo(PChar(TreeDataKlassen[Node^.Index].PfadSpalte1), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON) ;
      TreeDataKlassen[Node^.Index].IconIndexSpalte1 := Info.iIcon;
    end;

   ImageIndex := TreeDataKlassen[Node^.Index].IconIndexSpalte1;
  end;
end;
Zitat:

Übrigens:
Delphi-Quellcode:
procedure AddAllFilesInDir(const Dir: string; var List: TStringList);
List sollte
Delphi-Quellcode:
const
sein, nicht
Delphi-Quellcode:
var
, denn es soll ja nicht der Zeiger zur Liste geändert werden (können) sondern nur deren Inhalt.
Die Funktion verwende ich im Originalprojekt nicht. Die hab ich nur auf die Schnelle reingekloppt.

venice2 10. Dez 2020 21:02

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Zitat von Dalai (Beitrag 1478900)
Ist das denn richtig?
Delphi-Quellcode:
    if SHGetFileInfo(PChar(TreeDataKlassen[Node^.Index].PfadSpalte1), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON) = 0 then
    begin
     ImageIndex := TreeDataKlassen[Node^.Index].IconIndexSpalte1;
     // Eigentlich müsste das Icon angezeigt werden, wird es aber nicht.
    end;
Wird .IconIndexSpalte1 jemals gesetzt und wenn ja, wo?

Übrigens:
Delphi-Quellcode:
procedure AddAllFilesInDir(const Dir: string; var List: TStringList);
List sollte
Delphi-Quellcode:
const
sein, nicht
Delphi-Quellcode:
var
, denn es soll ja nicht der Zeiger zur Liste geändert werden (können) sondern nur deren Inhalt.

Grüße
Dalai

ja ist IO..
Ich sagte aber schon woran es liegt das Hicon wird nicht freigegeben.
Und einiges fehlt noch.

Ich kann hier 10000 Einträge laden ohne das irgendein Problem beim zeichnen hier auftritt.

venice2 10. Dez 2020 21:03

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Zitat von DieDolly (Beitrag 1478901)
Der Code da ist unwichtig, ist ein Fehler beim Kopieren passiert.
Es funktioniert ja ohnehin nicht, egal was ich mache und ob da jetzt eine Zuweisung fehlt.

Ich habe dieses Minimalbeispiel nur gebaut um grob zu zeigen wie alles aufgebaut ist. Und in der Hoffnung, dass ihr mir helfen könnt, SHGetFileInfo() dort richtig einzubauen.

So bekomme ich was angezeigt aber es ruckelt, zuckelt und führt sicher wieder zu fehlern.
Delphi-Quellcode:
procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex);
var
 Info: TSHFileInfo;
begin
 if (not(Column in [0, 1])) or (not Assigned(TreeDataKlassen)) then
  Exit;

 if Kind in [ikNormal, ikSelected] then
  begin
   if TreeDataKlassen[Node^.Index].IconIndexSpalte1 = -1 then
    begin
      SHGetFileInfo(PChar(TreeDataKlassen[Node^.Index].PfadSpalte1), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON) ;
      TreeDataKlassen[Node^.Index].IconIndexSpalte1 := Info.iIcon;
    end;

   ImageIndex := TreeDataKlassen[Node^.Index].IconIndexSpalte1;
  end;
end;

Ich kann.. warte noch ein kleines bisschen.

venice2 10. Dez 2020 21:47

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
preview.. 40566 Dateien scrolle ich ohne Probleme.
Kein Abstürze oder dergleichen.
Mit einer ImageList

https://www.magentacloud.de/lnk/ZOE1gPHT

DieDolly 10. Dez 2020 21:58

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Kannst du mir zeigen, wie du das umgesetzt hast?
Hat jede Datei ein festes Icon oder das was zur Datei dazugehört und dynamisch bestimmt?

venice2 10. Dez 2020 22:42

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Zitat von DieDolly (Beitrag 1478908)
Kannst du mir zeigen, wie du das umgesetzt hast?
Hat jede Datei ein festes Icon oder das was zur Datei dazugehört und dynamisch bestimmt?

Nun bei dem hier.. bekommst du ja nur ein festes Icon oder?
Delphi-Quellcode:
SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON);


Und zwar das des Laufwerks.
Das liegt dran weil du keine Datei zum auswerten vorgibst.


Dann verwendest du die falsche Funktion
Du muss dafür jedoch noch Vcl.ImgList in den uses hinzufügen.
Nicht VSTGetImageIndex sondern VSTGetImageIndexEx

Delphi-Quellcode:
procedure TForm1.VSTGetImageIndexEx(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex;
  var Ghosted: Boolean; var ImageIndex: TImageIndex;
  var ImageList: TCustomImageList);
var
 Info: TSHFileInfo;
begin
 if (not(Column in [0, 1])) or (not Assigned(TreeDataKlassen)) then
  Exit;

 if Kind in [ikNormal, ikSelected] then
  begin
     ImageIndex := TreeDataKlassen[Node^.Index].IconIndexSpalte1; // Den aktuellen Index der Node
  end;
end;
in create

Delphi-Quellcode:
   

   SmallImages := TImageList.Create(Self);
   SmallImages.ShareImages := True;
   VST.Images := SmallImages;
   VST.Images.ColorDepth := cd32Bit; // Unbedingt wichtig damit du keinen schwarzen Hintergrund bei den Icons hast
   VST.Images.DrawingStyle := dsTransparent; // Transparenz einschalten
   // *********
   TreeDataKlassen.Add(TreeData);
   ZeroMemory(@Info, SizeOf(TSHFileInfo)); // Speicher bereinigen

   SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_USEFILEATTRIBUTES or SHGFI_ICON or SHGFI_SYSICONINDEX or SHGFI_SMALLICON); //Icon Holen

   if Info.hIcon <> 0 then
   begin
     Icon := TIcon.Create;
     Icon.Handle := Info.hIcon;
     VST.Images.AddIcon(Icon); // VST.Images = SmallImages
     FreeAndNil(Icon);
   end;
Du kannst das Hicon noch freigeben nach FreeAndNil(Icon)
Delphi-Quellcode:
DestroyIcon(Info.hIcon);

glaube aber nicht das dass nötig ist weil TIcon ja nach der Übergabe der Eigentümer des handle ist und es auch frei gibt bei Free.

Ich hoffe du kommst klar.
teste es mit deinem minimalen Sample.

Dein Projekt zurück.. wenn es hilft gut wenn nicht ab in die Tonne. Siehe meine Kommentare im code
Habe genug mit dem Kram rum gespielt. Canvas erlaubt das zeichnen nun wieder sogar mit Icons

Meine Meinung VirtualStringTree ist einfach nur müll es ist nicht möglich an den Index der Node zu kommen.
So wie du das gerne möchtest ist es nicht möglich.

DieDolly 11. Dez 2020 08:26

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Ich hoffe du kommst klar.
Leider nicht, weil meine Ausgangsfrage nicht beantwortet wurde.
Ich weiß noch immer nicht, wie ich SHGetFileInfo richtig anwende, sodass ich jeweils das Icon habe, was zur Datei gehört.
Kommt das einfach in VSTGetImageIndexEx? Dann hab ich ja wieder die Ruckler und Aussetzer.

Moombas 11. Dez 2020 08:37

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
@Dolly: Evtl. hilft dir das, wenn nicht war es ein Versuch :)
So mache ich es in Lazarus (ohne ):
Delphi-Quellcode:
LargeIco, SmallIco : hIcon;
...
      ExtractIconEx(PChar(Pfad\Datei.exe), 0, LargeIco, SmallIco, 1);
      Icon.Handle := LargeIco;
      Icon.Transparent := True;
      ToolI.Picture.Icon := Icon;
So habe ich es vorher in Delphi gemacht:
Delphi-Quellcode:
icon  : TIcon;
Filter : word;
...
    Icon := TIcon.Create;
    try
      Icon.Handle:=ExtractAssociatedIcon(hInstance, PChar(ToolE.Text), Filter);
      ToolI.Picture.Icon := icon;
    finally
      icon.Free;
    end;

Aviator 11. Dez 2020 11:38

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Zitat:

Zitat von DieDolly (Beitrag 1478917)
Kommt das einfach in VSTGetImageIndexEx? Dann hab ich ja wieder die Ruckler und Aussetzer.

Naja bei den Remarks zu SHGetFileInfo im MSDN steht geschrieben, dass die Ausführung in einem Thread gemacht werden soll. Ansonsten kann es zu Rucklern bzw. Abstürzen führen. Siehe hier ...

Ich würde in dem Fall evtl. einen IconCache anlegen und dem beim Erstellen der Dateiliste füllen. Beim Zeichnen in OnGetImageIndex musst du dann nur noch den ImageIndex angeben. Kommt ein Dateityp hinzu der noch nicht in deinem IconCache enthalten ist, dann wird der hinzugefügt. Beim Zeichnen im Tree kannst du evtl. noch ein Fallback einbauen, dass ein Standardicon angezeigt wird, wenn der Thread Aufruf von SHGetFileInfo noch nicht abgeschlossen ist.


Das ist jetzt alles nur Theorie. Ich habe keinen SourceCode hierfür. Aber so sollte es funktionieren.

DieDolly 11. Dez 2020 11:38

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Damit habe ich dasselbe Problem wie mit SHGetFileInfo. Alles ruckelt und ist langsam gefolgt von seltsamen Canvas-Fehlern.
IconCache? Klingt irgendwie kompliziert und für mich nicht umsetzbar. Obwohl es interessant klingt. Würde man da einfach alle Dateiendungen die es gibt durchgehen, SHGetFileInfo aufrufen und sich das Info.iIcon holen?

Ich habe das jetzt so und es ruckelt ohne Ende.
Delphi-Quellcode:
procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
 Info: TSHFileInfo;
begin
 Node.SetData<TTreeData>(TreeDataKlassen[Node.Index]);

 if TreeDataKlassen[Node^.Index].IconIndexSpalte1 = -1 then
  begin
   SHGetFileInfo(PChar(TreeDataKlassen[Node^.Index].PfadSpalte1), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON);
   TreeDataKlassen[Node^.Index].IconIndexSpalte1 := Info.iIcon;
  end;
end;

procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: TImageIndex);
begin
 if (not(Column in [0, 1])) or (not Assigned(TreeDataKlassen)) then
  Exit;

 if Kind in [ikNormal, ikSelected] then
  begin
   ImageIndex := TreeDataKlassen[Node^.Index].IconIndexSpalte1;
  end;
end;
Wie man da mit der ImageList arbeiten soll, ist für mich immer noch ein großes Geheimnis.

venice2 11. Dez 2020 11:56

AW: VirtualStringTree - SHGetFileInfo hängt Programm auf / Canvas erlaubt kein Zeichn
 
Delphi-Quellcode:
   SHGetFileInfo(PChar(TreeDataKlassen[Node^.Index].PfadSpalte1), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_ICON or SHGFI_SMALLICON);
   TreeDataKlassen[Node^.Index].IconIndexSpalte1 := Info.iIcon;
Es wird immer ruckeln und du wirst immer die Ressourcen Probleme haben, von wegen kann nicht auf das Canvas zeichnen.
Es hat ganz einfach damit zu tun das du sehr viele Handles in den Speicher lädst und sie nicht freigibst.

Sorry aber du kannst das auf diese weise niemals in den griff bekommen weil Windows das nicht zulässt.
Und bedenke irgendwann ist das Limit an Handles erreicht und dann geht bei dir gar nichts mehr.
Und ja es gibt eine Beschränkung wie viele Handles ein Anwendung verwenden darf.

Genau wie dein vorheriges SystemImageList := SHGetFileInfo was zur folge hatte das überhaupt keine Icons geladen wurden.
Wie dem auch sei.. Tut mir leid für dich aber das ist der falsche weg.
Das VirtualStringTree macht es einen aber auch besonders schwer weil man nicht auf den Index jeder Node hin prüfen kann.
Deshalb macht eine ImageList auch keinen sinn wenn man sie mit nichts vergleichen kann.
Nun ist halt so.

Zitat:

Wie man da mit der ImageList arbeiten soll, ist für mich immer noch ein großes Geheimnis.
Kann man nicht weil du den Index vom ImageList mit nichts vergleichen kannst.
Wenn das gehen würde..
Delphi-Quellcode:
If ImageList.ImageIndex = NOde^.Index then


aber selbst das funktioniert nicht! Eine andere Lösung habe ich auch nicht gefunden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:21 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz