AGB  ·  Datenschutz  ·  Impressum  







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

Problem mit CustomCheckShellTreeView

Ein Thema von MiKaEr · begonnen am 23. Apr 2012 · letzter Beitrag vom 23. Apr 2012
Antwort Antwort
MiKaEr
(Gast)

n/a Beiträge
 
#1

Problem mit CustomCheckShellTreeView

  Alt 23. Apr 2012, 21:48
hallo,

auf die gefahr hin dass ich keine antworten bekomme frage ich trotzdem nach.

ich verwende folgende komponente um dateien und ordner in einer TShellTreeView mit CheckBoxen anzeigen zu lassen:
http://delphi.about.com/od/vclwritee...ocheck-stv.htm

vorher wurden keine dateien sondern nur ordner anzeigt. folgendes habe ich geändert und nun funktionierts:
Delphi-Quellcode:
procedure TGtroCustomCheckShellTreeView.AddFolder(Sender: TObject; AFolder: TShellFolder; var CanAdd: Boolean);
// Handler for the OnAddFolder event of TShellTreeView
// var
// FileExt: string;
begin
 // FileExt := ExtractFileExt(AFolder.DisplayName);
 // CanAdd := AFolder.IsFolder and (CompareText('.zip', FileExt) <> 0) and (CompareText('.cab', FileExt) <> 0)
 CanAdd := True;
end;
CanAdd ist jetzt immer True. vorher war es bei dateien egal welchem typs immer false (AFolder.isFolder and..).

Delphi-Quellcode:
function TGtroCustomCheckShellTreeView.GetNodePath(Node: TTreeNode): string;
// return the path of the folder associated with a node
// Called by CheckIt() and EnumFiles()
begin
 Result := TShellFolder(Node.Data).PathName;
end;

procedure TGtroCustomCheckShellTreeView.CheckIt(const Node: TTreeNode; IncludeSubs: Boolean; State: Boolean);
// called by WMLButtonDown() and LoadFromFile()
var
 Pattern: string;
 ANode: TTreeNode;
 Level: Integer;
begin
 Items.BeginUpdate;
 try
  SetNodeChecked(Node, State); // Check/uncheck the node
  EnumFiles(Node, State, FList);
  // Pattern := GetNodePath(Node) + '\'; // Get the path of the node (pattern)
  // if IncludeSubs then
  // begin
  // FPatterns.Add(Pattern + '/s'); // Load the pattern in the FPatterns list
  // Level := Node.Level;
  //
  // Node.Expand(True); // absolutely necessary as GetNext sees only visible nodes
  // try
  // ANode := Node.getFirstChild;
  // while (ANode <> nil) and (Level < ANode.Level) do
  // begin
  // if State <> IsNodeChecked(ANode) then
  // begin
  // SetNodeChecked(ANode, State);
  // EnumFiles(ANode, State, FList);
  // end;
  // ANode := ANode.GetNext;
  // end;
  // finally
  // Node.Collapse(True);
  // end;
  // end
  // else
  // FPatterns.Add(Pattern); // Load the pattern in the FPatterns list
 finally
  Items.EndUpdate;
 end; // try...finally
 if Assigned(FOnCheckChanged) then
  FOnCheckChanged(Self, Node, State, FList);
end;

procedure TGtroCustomCheckShellTreeView.EnumFiles(ANode: TTreeNode; State: Boolean; var List: TStringList);
// Called by CheckIt()
// var
// Path: string;
// Data: TSearchRec;
// ds: longint;
begin
 if State then
  List.Add(GetNodePath(ANode))
 else
  List.Delete(List.IndexOf(GetNodePath(ANode)));

 // Path := GetNodePath(ANode);
 // ds := FindFirst(Path + '\*.*', faAnyFile, Data); // Fetch the first file
 // while ds = 0 do // continue as long as the result is successfull
 // begin
 // if (Data.Attr and faDirectory <> faDirectory) then // don't bother with directories
 // if State then
 // List.Add(Path + '\' + Data.Name) // add to the list
 // else
 // List.Delete(List.IndexOf(Path + '\' + Data.Name)); // delete from the list
 // ds := FindNext(Data);
 // end;
 // FindClose(Data);
end;
beim ankreuzen eines ParentNodes (ist das der erste knotenpunkt eines ordners?) wurden alle unterordner/dateien mitangekreutzt. durch auskommentieren von dem code aus CheckIt() passiert das jetzt nicht mehr.

bei EnumFiles() habe ich alles auskommentiert weil wenn ich einen ordner ankreuze der VIEL inhalt hat das laden minuten dauert.

alles andere ist original.


meine frage bezieht sich jetzt auf die methode LoadFromFile(). eine datei mit zeilenweise enthaltenen pfaden zu dateien und ordnern wird korrekt eingelesen. aber hier krachts: IsNodeChecked()
Delphi-Quellcode:
function TGtroCustomCheckShellTreeView.IsNodeChecked(Node: TTreeNode): Boolean;
// Verifies if the node is checked
// Called by CheckIt(), UncheckAll(), WMLButtonDown() and LoadFromFile()
const
 TVIS_CHECKED = $2000;
var
 TvItem: TTVItem;
begin
 TvItem.Mask := TVIF_STATE;
 TvItem.hItem := Node.ItemId;
 TreeView_GetItem(Node.TreeView.Handle, TvItem);
 Result := (TvItem.State and TVIS_CHECKED) = TVIS_CHECKED;
end;
// . . .

// ein teil der LoadFromFile()-Procedure
if ANode <> nil then // Node has been found
     begin
      if not IncludeSubs then
       ANode.Collapse(False);
      OldState := IsNodeChecked(ANode); { GENAU hier kracht es mit einer AV } // Check status of node
      // Produce the list of files
      CheckIt(ANode, IncludeSubs, not OldState);
     end;
ANode ist ja so wie es aussieht ungleich nil und trotzdem kracht es beim prüfen ob die CheckBox des Knotenpunkt checked oder nicht checked ist.


ich entschuldige mich noch einmal ausdrücklich für meine dumme aufmüpfige art und weise. aber wenn etwas nicht klappt werde ich blöderweise schnell ungeduldig. ich werde es ändern!

Geändert von MiKaEr (23. Apr 2012 um 22:21 Uhr)
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: Problem mit CustomCheckShellTreeView

  Alt 23. Apr 2012, 22:16
Wie sieht denn "IsNodeChecked()" aus? Wahrscheinlich ist der Fehler dort drin...
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
MiKaEr
(Gast)

n/a Beiträge
 
#3

AW: Problem mit CustomCheckShellTreeView

  Alt 23. Apr 2012, 22:19
ich möchte nicht spammen, aber kopiere ich es aus dem oberen post noch einmal:
Delphi-Quellcode:
function TGtroCustomCheckShellTreeView.IsNodeChecked(Node: TTreeNode): Boolean;
// Verifies if the node is checked
// Called by CheckIt(), UncheckAll(), WMLButtonDown() and LoadFromFile()
const
 TVIS_CHECKED = $2000;
var
 TvItem: TTVItem;
begin
 TvItem.Mask := TVIF_STATE;
 TvItem.hItem := Node.ItemId;
 TreeView_GetItem(Node.TreeView.Handle, TvItem);
 Result := (TvItem.State and TVIS_CHECKED) = TVIS_CHECKED;
end;
durchdebuggt habe ich bereits und ANode hat immer den zugewiesenen wert "()" ohne anführungszeichen. ANode ist also nicht nil aber trotzdem in irgendeiner art und weise leer.
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Problem mit CustomCheckShellTreeView

  Alt 23. Apr 2012, 22:30
UPS - hatte ich übersehen. Weist Node.Treeview.Handle auf den korrekten Treeview? Was liefert Treeview_GetItem zurück? Und ist TvItem am Ende <> NIL?
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#5

AW: Problem mit CustomCheckShellTreeView

  Alt 23. Apr 2012, 22:33
ich kenne die Zusammenhänge nicht,
aber
Delphi-Quellcode:
var
 TvItem: TTVItem;
begin
 TvItem.Mask := TVIF_STATE;
wenn TTVItem kein Record sondern eine Klasse ist greift man hier ins Nirvana
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
MiKaEr
(Gast)

n/a Beiträge
 
#6

AW: Problem mit CustomCheckShellTreeView

  Alt 23. Apr 2012, 22:59
ich habe noch einmal durchdebuggt.

Delphi-Quellcode:
var
 TvItem: TTVItem;
begin
 TvItem.Mask := TVIF_STATE;
das hier ist fehlerfrei und wird sehr oft problemlos ausgeführt.

bei folgender zeile ist ANode nicht nil aber hat auch keinen wert:
if ANode <> nil then // Node has been found das ist das seltsame.

ich glaube die procedure LoadFromFile() ist fehlerhaft.
das wäre nicht der erste fehler den ich bei dieser komponente gefunden hätte.

wenn ich Oldstate := IsNodeChecked() aber auskommentiere tritt der fehler woanders auf:
Delphi-Quellcode:
procedure TGtroCustomCheckShellTreeView.SetNodeChecked(Node: TTreeNode; Checked: Boolean);
// Toggle the status of a node
// Called by CheckIt() and UncheckAll(),
const
 TVIS_CHECKED = $2000;
var
 TvItem: TTVItem;
begin
 FillChar(TvItem, SizeOf(TvItem), 0);
 with TvItem do
  begin
   hItem := Node.ItemId;
   Mask := TVIF_STATE;
   StateMask := TVIS_STATEIMAGEMASK;
   if Checked then
    TvItem.State := TVIS_CHECKED
   else
    TvItem.State := TVIS_CHECKED shr 1;
   TreeView_SetItem(Node.TreeView.Handle, TvItem); // HIER tritt der fehler dann mit einer AV auf
  end;
end;
das ist ja glaube ich auch logisch da ANode einfach keinen inhalt hat und das verstehe ich nicht.
das wäre also ein folgefehler aufgrund dessen dass ANode = '' ist.

folgende procedure ist dafür verantwortlich dass ANode eigentlich einen inhalt haben sollte.
Delphi-Quellcode:
function TGtroCustomCheckShellTreeView.GetNodeFromPath(const Path: string): TTreeNode;
// called by LoadFromFile()
var
 FoundNode: TTreeNode;

 function AppendSlash(ANode: TTreeNode): string;
 begin
  Result := TShellFolder(ANode.Data).PathName;
  if IsDirectory(Result) then
   if '\' <> Copy(Result, Length(Result), 1) then
    Result := Result + '\';
 end;

 procedure ScanNodes(Path: string; Segment: string; ANode: TTreeNode);
 var
  P: Integer;
  Slash: string;
 begin
  P := Pos('\', Path);
  if P > 0 then
   begin
    // Split the path into segments (segments are separated by "\")
    Segment := Segment + Copy(Path, 0, P); // First segment of the path
    Path := Copy(Path, P + 1, Length(Path)); // Remaining segments of the path
    ANode.Expand(False); // Expand the node
    ANode := ANode.getFirstChild; // Move to the first child node
    Slash := AppendSlash(ANode); // Append "\" if not already there
    while Segment <> Slash do // Iterate on each child nodes
     begin
      ANode := ANode.getNextSibling;
      if ANode <> nil then
       Slash := AppendSlash(ANode)
      else // Iterated beyond last child node
       Break; // No correspondence => out!
     end;
    if Path <> 'then // Path is not exhausted
     begin
      if ANode <> nil then
       begin
        ANode.Expand(False);
        ScanNodes(Path, Segment, ANode); // called recursively
       end;
     end
    else // Path is exhausted
     FoundNode := ANode; // Node found
   end;
 end;

begin
 ScanNodes(Path, '', Items[0]);
 Result := FoundNode; // Reference to the node if found; nil otherwise
end;
ich vermute den fehler sehr wahrscheinlich hier. beim durchdebuggen habe ich aber keinen gefunden.


gibt es keine andere möglichkeit bestimmte CheckBoxen bei einem Node Checked zu bekommen?
die oben liegenden Nodex bekomme ich alle Checked. aber wenn ich die Nodex mit for i := 0 to meinTreeView.Items.Count - 1 durchgehe werden nur wie gesagt die ersten Nodes bearbeitet und nicht die SubNodes. alle nodes auf verdacht expandieren kann ich auch nicht.

Geändert von MiKaEr (23. Apr 2012 um 23:07 Uhr)
  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 16:44 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