AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Application.CreateForm in einem Thread

Ein Thema von SneakyBagels · begonnen am 9. Mai 2017 · letzter Beitrag vom 10. Mai 2017
Antwort Antwort
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#1

AW: Application.CreateForm in einem Thread

  Alt 9. Mai 2017, 22:45
Hallo zusammen,

ich habe jetzt mal ein kleines Demo-Projekt zusammengebastelt und auch mit ein paar Kommentaren versehen. Natürlich wird hier nur ein ganz kleiner Teil der Funktionen des VST gezeigt. Aber für den Einstieg sollte das erst einmal reichen.

Wenn du das problemlos programmieren kannst, dann kannst du dich an die tieferen Funktionen des VST wagen.

Ich habe in dem Beispiel jetzt keinen Wert darauf gelegt alles in einen Thread auszulagern. In meinem Fall hat das alles sehr schnell funktioniert, sodass ich nicht die Notwendigkeit dafür gesehen habe. Zudem ist es ja erstmal nur ein kleines Projekt zum Testen. Das Auslagern in einen Thread sollte das kleinste Problem sein.

Auch ist der Code vielleicht nicht zu 100% optimiert, aber auch hier ... es ist ein Demo-Projekt.

Im Anhang habe ich jetzt mal die Release Variante des Projekts als Exe dringelassen falls das jemand nicht kompilieren kann. Erstellt wurde das Projekt mit Delphi 10 Seattle.

Viel Spaß beim Probieren @SneakyBagels und auch alle Anderen die sich mal mit dem VST beschäftigen wollen. Wenn Rückfragen aufkommen, dann einfach fragen. Ich denke es gibt auch noch divere andere User die hier weiterhelfen können wenn ich mal keine Zeit habe.

Verzeichnis-Browser.jpg
Angehängte Dateien
Dateityp: zip DirectoryBrowser.zip (1,48 MB, 11x aufgerufen)
  Mit Zitat antworten Zitat
SneakyBagels
(Gast)

n/a Beiträge
 
#2

AW: Application.CreateForm in einem Thread

  Alt 9. Mai 2017, 23:15
Ich habe gerade mal versucht hiermit ShellIcons anzeigen zu lassen. Klappt auch aber das zieht die Performance total in den Keller
Delphi-Quellcode:
procedure TfrmDirectoryBrowser.FormCreate(Sender: TObject);
var
 SysIL: HIMAGELIST;
 Info: TSHFileInfo;
 SmallImages: TImageList;
begin
 SmallImages := TImageList.Create(Self);
 SysIL := SHGetFileInfo('', 0, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON);

 if SysIL <> 0 then
  begin
   SmallImages.Handle := SysIL;
   SmallImages.ShareImages := True;
   vstDirectoryBrowser.Images := SmallImages;
  end;
.....
end;

procedure TfrmDirectoryBrowser.vstDirectoryBrowserGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
var
 NodeData: PDirectory;
 Info: TSHFileInfo;
begin
 NodeData := Sender.GetNodeData(Node);

 if NodeData^.iIconIndex = -1 then
  begin
   SHGetFileInfo(PChar(NodeData^.FullPath), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
   NodeData^.iIconIndex := Info.iIcon;
  end;

 ImageIndex := NodeData^.iIconIndex;
end;
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Application.CreateForm in einem Thread

  Alt 9. Mai 2017, 23:30
Hallo SneakyBagel,

letzter Beitrag für heute

Du machst da noch etwas falsch. Du darfst die ShellIcons nur 1x laden. Also z.B. in der LoadDirectories Methode. Spendiere der TDirectory Klasse dann zusätzlich noch eine Property ImageIndex. Beim Auslesen der Verzeichnisse lädtst du dann nur noch 1x das Icon.

Im GetImageIndex Event gibst du dem Tree immer nur noch den Index des Icons in der ImageList aus dem NodeData Object. Das dürfte die Performance erheblich verbessern.

EDIT: Wohoo. Passt gerade als Abschluss für heute (oh Moment, wir haben ja schon "morgen"). Der 1000. Beitrag ist gefallen.
  Mit Zitat antworten Zitat
SneakyBagels
(Gast)

n/a Beiträge
 
#4

AW: Application.CreateForm in einem Thread

  Alt 9. Mai 2017, 23:46
Ok dann für morgen
Delphi-Quellcode:
if (FindFirst(FFullPath + '*', faAnyFile, SR) = 0) then
    begin
     try
      repeat
       if ((SR.Name <> '.') and (SR.Name <> '..')) then // and ((SR.Attr and faDirectory) = faDirectory)) then
        begin
         Dir := TDirectory.Create(Format('%s%s\', [FFullPath, SR.Name]));
         Dir.FDirName := SR.Name;

         // An dieser Stelle müssen wir prüfen, ob das Verzeichnis Unterverzeichnisse besitzt
         // Dies wird benötigt, damit das "+" Symbol vor der Node angezeigt wird
         // Self.HasSubDirectories := CheckHasSubDirectories;

         Self.SubDirectories.Add(Dir);

         SHGetFileInfo(PChar(FFullPath + SR.Name), FILE_ATTRIBUTE_NORMAL, Info, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
         Self.iIconIndex := Info.iIcon;
        end;
      until (FindNext(SR) <> 0);
     finally
      FindClose(SR);
      FAlreadyLoaded := True;
     end;
    end;
Angezeigt bekomme ich zwar ein Icon, aber für alle Nodes dasselbe. Ein ganz komisches, teils grünes mit Anführungszeichen.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.966 Beiträge
 
Delphi 12 Athens
 
#5

AW: Application.CreateForm in einem Thread

  Alt 10. Mai 2017, 06:18
Allgemein zum VST:
Ich kann nur dazu raten das ganze generisch anzugehen und die Pointerspielerei nicht überall selbst zu machen...
Delphi-Quellcode:
  TBaseVirtualTreeHelper = class helper for TBaseVirtualTree
  public
    function Get<T: class>(Node: PVirtualNode): T;
  end;

{ TBaseVirtualTreeHelper }

function TBaseVirtualTreeHelper.Get<T>(Node: PVirtualNode): T;
var
  ResultData: Pointer;
begin
  ResultData := GetNodeData(Node);
  if Assigned(ResultData) and (TObject(ResultData^) is T) then
    Result := T(ResultData^)
  else
    Result := nil;
end;
Und dann in der Anwendung:
Delphi-Quellcode:
procedure TfrmDirectoryBrowser.vstDirectoryBrowserExpanding(Sender: TBaseVirtualTree; Node: PVirtualNode;
  var Allowed: Boolean);
var
  NodeData: TDirectory;
begin
  Allowed := True;

  NodeData := Sender.Get<TDirectory>(Node);
  NodeData.LoadSubDirectories; // ggf. auf Assigned prüfen
end;
Ein weiterer großer Vorteil ist, dass du im Debugger sofort den Inhalt sehen kannst ohne aufzuklappen:
VSTPointer.png
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Aviator

Registriert seit: 3. Jun 2010
1.611 Beiträge
 
Delphi 10.3 Rio
 
#6

AW: Application.CreateForm in einem Thread

  Alt 10. Mai 2017, 07:20
Angezeigt bekomme ich zwar ein Icon, aber für alle Nodes dasselbe. Ein ganz komisches, teils grünes mit Anführungszeichen.
Moin,

ich habe mir deinen Code zwar jetzt nicht eingebaut, aber du solltest beim OnGetImageIndex() Event folgendes beachten:

Prüfe immer den ImageKind der übergeben wird. Es gibt insgesamt 4 (?) Typen. (Habe den Source gerade nicht vorliegen, daher aus dem Kopf)
Delphi-Quellcode:
ikNormal, // Wird angezeigt wenn die Node keinen speziellen Zustand hat
ikSelected, // Wird angezeigt wenn die Node ausgewählt ist (Sei es durch FocusedNode oder das die Node in einer Selection enthalten ist)
ikState, // Habe ich bisher nie verwendet. Gibt aber wohl einen speziellen Status der Node an den man wohl wieder abfragen kann (bspw. wird gerade editiert oder so) (genauere Infos im SourceCode des VST)
ikOverlay // Das Image, dass nochmal über das eigentliche Image drübergepinselt werden soll (auch hier genauere Infos im SourceCode des VST)
In der Regel sind ikNormal und ikSelected die beiden meist benötigten Typen. Deshalb solltest du in dein OnGetImageIndex() Event die folgende Abfrage mit aufnehmen. Eventuell ist dadurch dein Problem schon behoben. Wenn nicht, dann solltest du dir die Images in der ImageList eventuell mal alle in einer PaintBox nebeneinander malen und sie dir anschauen.

Delphi-Quellcode:
procedure TfrmDirectoryBrowser.vstDirectoryBrowserGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
var
 NodeData: PDirectory;
 Info: TSHFileInfo;
begin
  if (Kind in [ikNormal, ikSelected]) then begin // Die Zeile hinzufügen (es sei denn du wolltest die speziellen Typen behandeln)
    NodeData := Sender.GetNodeData(Node);
    ImageIndex := NodeData^.iIconIndex;
  end;
end;
@Jaenicke: Ja kann man so machen.
Ich konnte mich allerdings bisher nicht an die Umstellung auf Generics in Bezug auf den VST gewöhnen. Überall anders im Programm wird massiv mit Generics gearbeitet. Die Einführung kam ja irgendwann mit Version 6.X. Ich bin dabei seit den frühereren 4.X Versionen als er noch von Mike Lischke programmiert wurde. Und da war das alles noch ganz anders

Geändert von Aviator (10. Mai 2017 um 07:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.966 Beiträge
 
Delphi 12 Athens
 
#7

AW: Application.CreateForm in einem Thread

  Alt 10. Mai 2017, 10:25
Ich konnte mich allerdings bisher nicht an die Umstellung auf Generics in Bezug auf den VST gewöhnen.
Das ist ja der Helper für die alten Versionen. Die generische Variante direkt habe ich selber noch kaum benutzt.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:47 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