Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   TreeView mit Find und Filter (https://www.delphipraxis.net/110095-treeview-mit-find-und-filter.html)

taaktaak 12. Mär 2008 21:13


TreeView mit Find und Filter
 
Liste der Anhänge anzeigen (Anzahl: 1)
Moin, Moin,
seit einigen Tagen bastle ich an einer Erweiterung von TCustomTreeView (ok, mir ist bekannt, dass es VirtualTreeView gibt - aber ich möchte einfach das TreeView besser kennen lernen).

Die neuen Funktionalitäten bestehen aus einem "Standard-Popupmenü", das die Komponente jedem Programm zur Verfügung stellt. Integriert in dieses Popup sind 4 Funktionen, insbesondere "Find" und "Filter". Da ich jetzt langsam aber sicher betriebsblind werde, wäre es schön, wenn sich mal einer das angefügte Testprogramm vornimmt, das Popup testet und Verbesserungsvorschläge macht / Fehler aufspürt. Das Programm ist natürlich NUR zum Testen gedacht, es hat keinen praktischen Nutzen.

Vorab schon mal ein herzliches Dankeschön!

Aurelius 13. Mär 2008 07:41

Re: TreeView mit Find und Filter
 
Hi taaktaak.

1.) die Suche findet gar nix
2.) wenn man mit rechts auf ein item klickt sollte das auch markiert werden

taaktaak 13. Mär 2008 11:35

Re: TreeView mit Find und Filter
 
Hallo xX0815Xx
vielen Dank für den Test!
Allerdings merkwürdig, dass die Suche nichts findet. Das kann ich nicht reproduzieren. Sowohl bei Eingabe eines eindeutigen Suchtextes als auch bei Verwendung von WildCards funktioniert das mit der zur Verfügung gestellten Exe bei mir einwandfrei!? Nach welchem Begriff hast du gesucht?
Die Markierung auch mit Rechtsklick kann natürlich zusätzlich vorgesehen werden.

Aurelius 13. Mär 2008 12:02

Re: TreeView mit Find und Filter
 
Das geht doch, ich hab nicht gewusst dass der der genaue Begriff gesucht wird :wall:

taaktaak 13. Mär 2008 12:28

Re: TreeView mit Find und Filter
 
Hallo xX0815Xx
aber auch die Suche mit Wildcards sollte immer funktionieren - oder?

Aurelius 13. Mär 2008 12:41

Re: TreeView mit Find und Filter
 
Ja, das funktioniert einwandfrei :thumb:

Da ich im Augenblick selbst mit einer TreeView arbeite und diese auch durchsuchen möchte fände ich es toll wenn du die Suchprozedur veröffentlichen würdest :)

taaktaak 13. Mär 2008 15:14

Re: TreeView mit Find und Filter
 
Ja, das ist kein Problem, kommt heute Abend :thumb:

Aurelius 13. Mär 2008 15:17

Re: TreeView mit Find und Filter
 
Super von dir :thumb:

taaktaak 13. Mär 2008 18:46

Re: TreeView mit Find und Filter
 
Moin, Moin xX0815Xx,
hier mal der relevante Ausschnitt der Suchprozedur...

Delphi-Quellcode:
.
..
SetHourglass(true);

SetLength(FindList,0);

for i:=0 to pred(TreeView~~.Items.Count) do
  if MatchStr(TreeView~~.Items[i].Text,Pattern,CaseSensitive) then begin
    SetLength(FindList,High(FindList)+2);
    FindList[High(FindList)]:=i
    end;

SetHourglass(false);

N:=High(FindList)+1;
if N=0 then Dialog(1,-1,-1,1,-1,
                  'No matching tree item found ...',
                  'Ok','','','')

       else ...
Der Prozedur wird das Suchmuster in "Pattern" und der Status der Checkbox in "CaseSensitive" übergeben. Wesentlich ist lediglich die Schleife, für jedes gefundene Item wird dessen TreeIndex in ein dynamisches Array abgelegt, damit dann mittels der beiden Buttons FindPrev FindNext alle Fundstellen angezeigt werden können. Dialog() ist eine spezielle Anzeigefunktion, also so was ähnliches wie ShowMessage(). Obwohl die Verwendung von TreeView.Items ziemlich langsam ist, ist die Geschwindigkeit auch bei mehreren tausend TreeItems noch akzeptabel.


Die Funktion MatchStr() ist für den Zeichenkettenvergleich (incl. WildCards) zuständig.

Delphi-Quellcode:
function MatchStr(Source,Pattern:String;CaseSensitive:Boolean):Boolean;

  function Match(Source,Pattern:PChar):Boolean;
  begin                                  
    if StrComp(Pattern,'*')=0 then Result:=true
                              else
      if (Source^=Chr(0)) and
         (Pattern^<>Chr(0)) then Result:=false
                            else
        if Source^=Chr(0) then Result:=true
                          else
          case Pattern^ of
          '*': if Match(Source,@Pattern[1]) then Result:=true
                                            else Result:=Match(@Source[1],Pattern);
          '?': Result:=Match(@Source[1],@Pattern[1]);
 
          else if Source^=Pattern^ then Result:=Match(@Source[1],@Pattern[1])
                                   else Result:=false;
          end;
  end;

begin
  if not(CaseSensitive) then begin
    Source :=AnsiLowerCase(Source);
    Pattern:=AnsiLowerCase(Pattern);
    end;

  Result:=Match(PChar(Source),PChar(Pattern))
end;
An der Filterfunktion bastle ich übrigens noch. Da die TreeViewNodes keine Visible-Eigenschaft haben, müssen für die gefilterte Anzeige alle "nicht passenden" Nodes aus dem Tree entfernt werden. Das kann mit Item.Delete natürlich innerhalb einer Schleife ohne Aufwand realisiert werden - ist aber inakzeptabel langsam.

Zuerst hatte ich das Filtern dann mit einem Stream und einer Stringlist realisiert: Die Geschwindigkeit war daraufhin etwa 50-60 mal schneller. Das Vorgehen hatte aber den Nachteil, dass die "übrigen" Node-Informationen wie .ImageIndex, .SelectedIndex, .StateIndex und .Data verloren gingen. Ist natürlich ebenfalls nicht praktikabel.

Derzeit werden diese Daten in einem zusätzlichen Record-Array "gerettet" und wiederhergestellt. Dadurch ist es wieder etwas langesamer, aber immer noch ausreichend schnell.

Da das Ganze jetzt aber sehr "aufgebläht" ist, bastle ich derzeit an einer Lösung mit dem ObjectStream - der diese Informationen ja beinhaltet. Da es mir nicht gelungen ist, den Source der Speicherung gänzlich nachzuvollziehen, versuche ich derzeit das Schema der Binärdaten im Stream aufzuschlüsseln. Wenn das gelungen ist und das alles mit dem ObjectStream realisiert werden kann, werde ich den Source -sofern Interesse besteht- auch zur Verfügung stellen.

Aurelius 14. Mär 2008 07:28

Re: TreeView mit Find und Filter
 
Danke, ich werds mir mal zu Gemüte führen :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:02 Uhr.

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