Delphi-PRAXiS

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/)
-   -   Delphi TTreeView Frage (https://www.delphipraxis.net/156357-ttreeview-frage.html)

Ascuriah 29. Nov 2010 14:33

TTreeView Frage
 
Hallo DP'ler

Ich hab ein Problem, ich hab mir ne Procedur geschrieben die einen bestimmten Pfad als TreeView angiebt. Problem daran ist, das aus dem gewählten Pfad in jedem Level nur bestimmte Ordner angezeigt bzw zum View hinzugefügt werden.
Die Procedur sieht wie folgt aus:

Delphi-Quellcode:
procedure TForm1.ShowDirectory(_Tree: TTreeView; _sVerzeichnis: string; _KnotenRoot: TTreeNode);
{$region 'Kommentar ShowDirectory( _Tree:TTreeView, _sVerzeichnis:string, _Eintrag:TTreeNode, )'}
{*
   Beschreibung : Procedur baut aus einer Pfadangabe einen TreeView
 
   @param _Tree : der Tree der neu erstellt wird
   @param _sVerzeichnis : das QuellVerzeichnis aus dem der Tree entsteht
   @param _Eintrag : der erste Startknoten
}
{$endregion}
var
   SearchRec : TSearchRec;
   KnotenNeu : TTreeNode;
   verz, str : string;
   i : integer;
begin
   verz := _sVerzeichnis;
   _Tree.Items.BeginUpdate;
   verz := IncludeTrailingPathDelimiter(verz);
   if FindFirst(verz + '*.*',faDirectory, SearchRec) = 0 then
   begin
      repeat
         if (SearchRec.Attr and faDirectory = faDirectory) and
         ((SearchRec.Name[1] = 'K') or
         (SearchRec.Name[1] = 'M') or
         (SearchRec.Name[1] = 'F') or
         (SearchRec.Name[1] = '0')) then
         begin
            if ((SearchRec.Attr and faDirectory) <> 0) then
            begin
               _KnotenRoot := _Tree.Items.AddChild(_KnotenRoot, SearchRec.Name);
               KnotenNeu := _KnotenRoot.Parent;
               ShowDirectory(_Tree, verz + SearchRec.Name, _KnotenRoot);
               _KnotenRoot := KnotenNeu;
            end;

         end;
      until FindNext(SearchRec) <> 0 ;
      FindClose(SearchRec);
   end;
   _Tree.Items.EndUpdate;
end;
Ziel ist jetzt das in Level 0 nur die Ordner hinzugefügt werden sollen bei dehnen SearchRec.Name[1] ein K ist und SearchRec.Name[2] eine Ziffer.
Bei Level 1 SearchRec.Name[1] ein M und SearchRec.Name[2] eine Ziffer und bei Level 2 dürfen nur noch Ordner hinzugefügt werden die mit der Ziffer [01] beginnen.
Das ganze funktioniert auch halb mit den 4 Vergleichen die ich oben gemacht habe aber ich kriegs einfach ned hin den SearchRec.Name[2] mit zu überprüfen.

Vielleicht weis ja jemand von euch Rat oder ne Idee wie das noch viel leichter geht
mfg
Ascu

shmia 29. Nov 2010 15:12

AW: TTreeView Frage
 
Zitat:

Zitat von Ascuriah (Beitrag 1064789)
...oder ne Idee wie das noch viel leichter geht

Ich würde mir eine Filterfunktion schreiben:
Delphi-Quellcode:
function FilterDirectory(const dirname:string; level:integer):boolean;
begin
  result := false;
  if (level = 0) and (Length(dirname) >= 2) and (dirname[1]='K') and IsDigit(dirname[2]) then
    Result := True
  else if (level = 1) and ...
    ...
end;
Und dann in deiner Procedure ShowDirectory:
Delphi-Quellcode:
if ((SearchRec.Attr and faDirectory) <> 0) and FilterDirectory(SearchRec.Name, level) then
begin
Dann musst du dir noch überlegen, wie du an den Level kommst.
Evtl. kann man das über _KnotenRoot.Level abgreifen oder man muss den Level schon der procedure ShowDirectory als Parameter mitgeben.

Ascuriah 29. Nov 2010 15:21

AW: TTreeView Frage
 
HM wo hast du IsDigit her bzw welche Unit muss dafür eingebunden werden?

s.h.a.r.k 29. Nov 2010 15:24

AW: TTreeView Frage
 
An sich wäre die ja selbst schnell geschrieben, oder? ;)

Aber die Funktion gibts schon in der Unit Character.

Ascuriah 29. Nov 2010 15:29

AW: TTreeView Frage
 
AH ok ja hab se selbst gemacht eben :D und seh auch grad das mein Delphi mit der Unit Character ned klar kommt bzw keine findet hm...

s.h.a.r.k 29. Nov 2010 15:53

AW: TTreeView Frage
 
Nutze gerade Delphi 2010 -- da ists jedefalls mit dabei ;) Keine Ahnung was du für eine Version nutzt, hast keine in deinem Profil angegeben.

Ascuriah 29. Nov 2010 15:58

AW: TTreeView Frage
 
hm habs jetzt so:

Delphi-Quellcode:
function TForm1.FilterDirectory(_dirname: string; _level: integer): boolean;
begin
   Result := false;
   if (_level = 0) and (Length(_dirname) >= 2) and (_dirname[1]='K') and TOlapExtraktorBase.isnumeric(_dirname[2])
   then
      Result := true
   else
   if (_level = 1) and (Length(_dirname) >= 2) and (_dirname[1]='M') and TOlapExtraktorBase.isnumeric(_dirname[2])
   then
      Result := true
   else
   if (_level = 2) and (Length(_dirname) >= 2) and (_dirname[1]='F') and TOlapExtraktorBase.isnumeric(_dirname[2])
   then
      Result := true
   else
   if (_level = 3) and (Length(_dirname) >= 2) and TOlapExtraktorBase.isnumeric(_dirname[1]) and
   TOlapExtraktorBase.isnumeric(_dirname[2]) then
      Result := true
   else
   begin
      ShowMessage('FEHLER');
   end;
end;
und so:

Delphi-Quellcode:
procedure TForm1.ShowDirectory(_Tree: TTreeView; _sVerzeichnis: string; _KnotenRoot: TTreeNode);

{$region 'Kommentar ShowDirectory( _Tree:TTreeView, _sVerzeichnis:string, _Eintrag:TTreeNode, )'}
{*
   Beschreibung : Procedur baut aus einer Pfadangabe einen TreeView
 
   @param _Tree : der Tree der neu erstellt wird
   @param _sVerzeichnis : das QuellVerzeichnis aus dem der Tree entsteht
   @param _Eintrag : der erste Startknoten
}
{$endregion}
var
   SearchRec : TSearchRec;
   KnotenNeu : TTreeNode;
   verz, str : string;
   i : integer;
begin
   verz := _sVerzeichnis;
   _Tree.Items.BeginUpdate;
   verz := IncludeTrailingPathDelimiter(verz);
   if FindFirst(verz + '*.*',faDirectory, SearchRec) = 0 then
   begin
      repeat
         if (SearchRec.Attr and faDirectory = faDirectory) and FilterDirectory(SearchRec.Name, 0) then
         begin
            if ((SearchRec.Attr and faDirectory) <> 0) then
            begin
               _KnotenRoot := _Tree.Items.AddChild(_KnotenRoot, SearchRec.Name);
               KnotenNeu := _KnotenRoot.Parent;
               ShowDirectory(_Tree, verz + SearchRec.Name, _KnotenRoot);
               _KnotenRoot := KnotenNeu;
            end;

         end;
      until FindNext(SearchRec) <> 0 ;
      FindClose(SearchRec);
   end;
   _Tree.Items.EndUpdate;
end;
hab zum testn mal beim level einfach 0 genommen aber er schmeist mir jetzt die ShowMessage, das heist irgendwas passt ned. Meine is numeric sieth so aus:
Delphi-Quellcode:
class function TOlapExtraktorBase.IsNumeric(_value: string): boolean;
var
   i: integer;
begin
   result := true;
   try
   i := StrToInt(_value);
   except
   result := false;
   end;
end;
Wenn ich in der Filter Funktion den Else ShowMessage Teil weglasse schmeist er mir folgenden Fehler:

Erste Gelegenheit für Exception bei $75E39617. Exception-Klasse EConvertError mit Meldung ''M' ist kein gültiger Integerwert'. Prozess OlapUI.exe (5048)
Bin grad bissle überfragt was da ned passt ;(

shmia 29. Nov 2010 16:10

AW: TTreeView Frage
 
1.) das ShowMessage('FEHLER') gehört da nicht hin; einfach weglassen
Schliesslich gibt es die beiden Verzeichnisse "." und ".." und die sollen ausgefiltert werden.
2.) deine Funktion IsNumeric() hat den falschen Namen und passt auch Inhaltlich nicht.
Digit (deutsch: Ziffer) ist das was wir prüfen wollen.
Delphi-Quellcode:
function CharIsDigit(const C: Char): Boolean;
begin
  Result := (C >= '0') and (C <='9');
end;
Deine function TOlapExtraktorBase.IsNumeric stiftet schon vom Namen her Verwirrung!
Was hat die Prüfung eines Strings mit OLAP zu tun?
Wenn es jetzt class function TStringUtils.IsNumeric heisen würde, dann wäre es akzeptabel.
Aber ein ganz normale Funktion ist das was am Meisten Sinn macht.

Ascuriah 30. Nov 2010 07:24

AW: TTreeView Frage
 
Jo stimmt schon bin noch relativ neu in Delphi, Konventionen vergess ich noch gern^^.

Olap kommt davon das solche Unterstützungsfunktionen in meiner Base-Unit liegen und mein Projekt ein Olap-Datenextraktor ist. Eine eigene Utils-Unit ist aber gerade im entstehen.

Die ShowMessage nutze ich nur um direkt zu sehen ob der Fehler ausgelöst wird. Die kommt selbstverständlich raus. Ich weis das man das auch via exception mit try und except machen kann falls ein Fehler ausgelöst wird aber darin bin ich noch ned ganz so fit.

Naja klappt soweit schon ganz gut muss mir nur noch überlegen wie ich ihm den Level übegebe, dann passts;)

Ascuriah 30. Nov 2010 09:24

AW: TTreeView Frage
 
Hm wenn ich der FilterDirectory Funktion _KnotenRoot.Level übergebe schmeist er mir den Fehler:

Exception-Klasse EAccessViolation mit Meldung 'Zugriffsverletzung bei Adresse 004F59E4 in Modul 'OlapUI.exe'. Lesen von Adresse 00000004'. Prozess OlapUI.exe (5428)

Vielleicht hat jemand ne Idee wie ich das Level da übergeben kann, ich stell mich anscheined einfach zu blöd an...

DeddyH 30. Nov 2010 09:42

AW: TTreeView Frage
 
Irgendwie sieht mir das zu kompliziert aus. Ginge das nicht auch einfach so (aus dem Kopf getippt, daher ungetestet)?
Delphi-Quellcode:
procedure TForm1.ShowDirectory(_Tree: TTreeView; const _sVerzeichnis: string; _KnotenRoot: TTreeNode);

{$region 'Kommentar ShowDirectory( _Tree:TTreeView, _sVerzeichnis:string, _Eintrag:TTreeNode, )'}
{*
   Beschreibung : Procedur baut aus einer Pfadangabe einen TreeView
 
   @param _Tree : der Tree der neu erstellt wird
   @param _sVerzeichnis : das QuellVerzeichnis aus dem der Tree entsteht
   @param _Eintrag : der erste Startknoten
}
{$endregion}
var
   SearchRec : TSearchRec;
   KnotenNeu : TTreeNode;
   verz : string;
begin
   Assert(Assigned(_Tree));
   verz := IncludeTrailingPathDelimiter(_sVerzeichnis);
   _Tree.Items.BeginUpdate;
   try
     if FindFirst(verz + '*.*',faDirectory, SearchRec) = 0 then
     try
        repeat
           if (SearchRec.Attr and faDirectory = faDirectory) and
              (SearchRec.Name <> '.') and
              (SearchRec.Name <> '..') then
           begin
              KnotenNeu := _Tree.Items.AddChild(_KnotenRoot, SearchRec.Name);
              ShowDirectory(_Tree, verz + SearchRec.Name, KnotenNeu);
           end;
        until FindNext(SearchRec) <> 0 ;
     finally
        FindClose(SearchRec);
     end;
   finally
     _Tree.Items.EndUpdate;
   end;
end;
[edit] Achja, BeginUpdate und EndUpdate sind wohl in der aufrufenden Routine besser aufgehoben als in der Rekursion. Trotzdem lass ich das erstmal so. [/edit]

Ascuriah 1. Dez 2010 10:57

AW: TTreeView Frage
 
Moin Moin

Ich ruf den Thread hier wieder auf da ich denk das das zur selben Thematik bezüglich TreeView gehört.
Undzwar habe ich meine Funktion zum Erstellen des TreeViews jetzt umgebaut und sie funktioniert tadellos.

Kann mir jemand sagen welches Ereigniss ich nutzen muss, um bei einem Doppelklick auf einen Knoten, diesen in ein Memo oder ein ListView einfügen kann? (Das normale dblClick-Event kann ich nicht nutzen da dieses ja fur den ganzen Baum, sprich auch für den leeren weißen Bereich gilt, es aber nur beim dbl-klicken auf einen Knoten auslösen darf.

Ich hoffe die Problematik wird einigermaßen klar

mfg

DeddyH 1. Dez 2010 12:02

AW: TTreeView Frage
 
Doch, OnDblClick geht.
Delphi-Quellcode:
procedure TForm1.TreeView1DblClick(Sender: TObject);
var Item: TTreeNode;
    P: TPoint;
begin
  //Maus- in Clientkoordinaten umrechnen
  P := Treeview1.ScreenToClient(Mouse.CursorPos);
  //Knoten an dieser Stelle ermitteln
  Item := Treeview1.GetNodeAt(P.X, P.Y);
  //wenn einer da -> ausgeben
  if Assigned(Item) then
    ShowMessage(Item.Text);
end;

Ascuriah 1. Dez 2010 12:13

AW: TTreeView Frage
 
Hey klasse das funktionert prima danke noch ma da wär ich niemals draufgekommen.

Ascuriah 28. Dez 2010 14:09

AW: TTreeView Frage
 
Zitat:

Zitat von DeddyH (Beitrag 1065370)
Doch, OnDblClick geht.
Delphi-Quellcode:
procedure TForm1.TreeView1DblClick(Sender: TObject);
var Item: TTreeNode;
    P: TPoint;
begin
  //Maus- in Clientkoordinaten umrechnen
  P := Treeview1.ScreenToClient(Mouse.CursorPos);
  //Knoten an dieser Stelle ermitteln
  Item := Treeview1.GetNodeAt(P.X, P.Y);
  //wenn einer da -> ausgeben
  if Assigned(Item) then
    ShowMessage(Item.Text);
end;

Hm das Problem daran ist, das nur auf einen Doppelclick direkt auf den Text die Funktion auslösen darf, mach ich das so wie du hier geschrieben hast, dann reagiert die Funktion auch auf DoppelClicks auf den erweitern/verstecken Pfeil. Ich müsste es irgendwie hinkriegen das nur auf einen Doppelklick genau auf den Text die Funktion weiterläuft


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:39 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