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 VirtualStringTree - FullExpand Problem (https://www.delphipraxis.net/128247-virtualstringtree-fullexpand-problem.html)

UMOL 26. Jan 2009 21:29


VirtualStringTree - FullExpand Problem
 
Hallo zusammen

Folgendes Szenario:
In meinem Programm wird ein VirtualStringTree aus einer MemIniFile aufgebaut. Aus verschiedenen Gründen muß der VirtualStringTree auf FullExpand gesetzt werden; gleichzeitig aber die Möglichkeit bieten, beim Aufruf von ToggleNode ein Node zusammen oder auseinander zu falten. Mein Code sieht so aus (Content ist eine MemIniFile):


Delphi-Quellcode:
procedure TForm1.VirtualStringTree1GetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var
  s: String;
  SL: TStringList;
begin
  SL := TStringList.Create;
  case Column of
    0:
      begin
          if VirtualStringTree1.GetNodeLevel(Node) = 0 then
          begin
            Content.ReadSections(SL);
            s := SL[Node.Index];
            CellText := s;
            Content.ReadSection(s, SL);
            if VirtualStringTree1.ChildCount[Node] <> Cardinal(SL.Count) then
              VirtualStringTree1.ChildCount[Node] := SL.Count;
          end
          else
          begin
            Content.ReadSections(SL);
            Content.ReadSection(SL[Node.Parent.Index], SL);
            CellText := SL[Node.Index];
          end;
        end;
    1:
      if VirtualStringTree1.GetNodeLevel(Node) = 0 then
        CellText := ''
      else
      begin
        Content.ReadSections(SL);
        s := SL[Node.Parent.Index];
        Content.ReadSection(s, SL);
        CellText := Content.ReadString(s, SL[Node.Index], 'n/a')
      end;
  end;
  SL.Free;
  {We cannot use VirtualStringTree1.FullExpand(nil) to expand all nodes as it
  causes the main menu bar to stop responding.}
  if Node^.Parent = Sender.RootNode then
    VirtualStringTree1.Expanded[Node] := True;
end;


procedure TForm1.VirtualStringTree1InitNode(Sender: TBaseVirtualTree;
  ParentNode, Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
begin
  if (VirtualStringTree1.GetNodeLevel(Node) = 0) then
    VirtualStringTree1.CheckType[Node] := ctButton;
end;


procedure TForm1.VirtualStringTree1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  HIF: THitInfo;
  Node: PVirtualNode;
begin
  if ssLeft in Shift then
  begin
    VirtualStringTree1.GetHitTestInfoAt(X,Y,true,HIF);
    if hiOnItemCheckbox in HIF.HitPositions then
    begin
      Node := VirtualStringTree1.GetNodeAt(X,Y);
      VirtualStringTree1.ToggleNode(Node);
    end;
  end;
end;

Klappt soweit auch alles wie geplant - alle Nodes sind expandiert und der Button links von der Node Caption wird angezeigt. Mein Problem ist nur, daß ein Click auf den Button nicht ToggleNode(Node) aufruft. Ich weiß, daß ich nur die letzten beiden Zeilen aus OnGetText löschen muß, damit der Button reagiert, aber dann stehe ich vor dem Dilemma, daß die Nodes nicht mehr expandiert sind. Ich habe versucht, die beiden Zeilen im OnInitNode und diviersen anderen Events unterzubringen, aber leider ohne Erfolg. Entweder sind alle Nodes zusammengefaltet, oder aber der Button reagiert nicht. Weiß jemand, was ich hier falsch mache? Ich hab jetzt schon drei Tage nach einer Lösung gesucht und dabei meine letzten Haare eingebüßt...

Danke im voraus
Gruß
Uwe

nuclearping 26. Jan 2009 21:33

Re: VirtualStringTree - FullExpand Problem
 
Pack deinen Code bitte in [ delphi ]...[ /delphi ] Tags. So kann das keiner lesen - und so will ich's auch nicht entziffern.

UMOL 26. Jan 2009 21:39

Re: VirtualStringTree - FullExpand Problem
 
Zitat:

Zitat von nuclearping
Pack deinen Code bitte in [ delphi ]...[ /delphi ] Tags. So kann das keiner lesen - und so will ich's auch nicht entziffern.

Sorry, die Option hatte ich übersehen.

Uwe

nuclearping 26. Jan 2009 21:43

Re: VirtualStringTree - FullExpand Problem
 
Dir ist klar, dass OnGetText ca. zwölfzigtausend mal pro Sekunde ausgelöst wird?

UMOL 26. Jan 2009 21:53

Re: VirtualStringTree - FullExpand Problem
 
Ist mir schon klar, aber wenn ich

Delphi-Quellcode:
if Node^.Parent = Sender.RootNode then
  VirtualStringTree1.Expanded[Node] := True;
in OnInitNode setze, dann werden die Nodes nicht ausgeklappt. Das ist genau mein Problem.

Uwe

nuclearping 26. Jan 2009 21:55

Re: VirtualStringTree - FullExpand Problem
 
Warum klappst du die Knoten nicht nach dem Laden des Baums aus?

UMOL 26. Jan 2009 21:58

Re: VirtualStringTree - FullExpand Problem
 
In welchem Event? Ich habe sämtliche in Frage kommenden ausprobiert und drehe mich im Kreis: entweder sind die Nodes ausgeklappt und die Buttons reagieren nicht, oder die Buttons reagieren, aber die Nodes sind zusammengefaltet.

nuclearping 27. Jan 2009 10:34

Re: VirtualStringTree - FullExpand Problem
 
Ich meine dann, wenn du fertig bist mit dem Laden aus der MemIni.
Delphi-Quellcode:
procedure TMyClass.BuildTree;
begin
  OpenMemIni;
  CreateVSTStructure;
  VST.FullExpand;
  CloseMemIni;
end;

jbg 27. Jan 2009 11:11

Re: VirtualStringTree - FullExpand Problem
 
Zitat:

Zitat von UMOL
in OnInitNode setze, dann werden die Nodes nicht ausgeklappt. Das ist genau mein Problem.

Wie wäre es mit folgendem im OnInitNode.
[delphi]Include(InitialStates, ivsExpanded);[/quote]

UMOL 27. Jan 2009 17:04

Re: VirtualStringTree - FullExpand Problem
 
@jbg

Danke für den Hinweis, aber mit dem Setzen des InitialStates habe ich es schon versucht. Führt in meinem Fall leider nicht zum Erfolg.


@nuclearping

Hm, das ist doch genau das, was ich momentan im OnGetText Event mache. In welchem Event soll ich deine Prozedur BuildTree dann aufrufen? Wenn ich es im OnGetText oder OnInitNode Event mache, kriege ich logischerweise dasselbe Ergebnis wie bisher.

Ich glaube mittlerweile, daß mein Problem anders geartet ist. Wahrscheinlich muß ich doch den umständlichen Weg gehen und erst eine Record Structure aufbauen und diese mit OnInitNode initialisieren, statt das ganze in einem Rutsch im OnGetText zu erledigen. Das wollte ich eigentlich vermeiden, und laut Dokumentation sollte das in diesem Fall auch nicht nötig sein.

Danke euch beiden
Uwe

nuclearping 27. Jan 2009 19:12

Re: VirtualStringTree - FullExpand Problem
 
Entweder wir reden von zwei unterschiedlichen Sachen oder du verstehst nicht, was ich meine.

In keinem Event. Jedesmal wenn du einen neuen Knoten hinzufügst oder mit dem kompletten Aufbau des Baums fertig bist, machst du FullExpand.

UMOL 27. Jan 2009 19:55

Re: VirtualStringTree - FullExpand Problem
 
Ich glaube, wir reden aneinander vorbei... ;-)

Schau dir bitte meine OnGetText Prozedur nochmal an. Dort wird der Tree komplett aufgebaut, und nach dem Aufbau wird FullExpand aufgerufen. Also so, wie du es vorschlägst. ToggleNode wird in diesem Fall nicht ausgelöst, weil OnGetText - wie du richtigerweise erwähnt hattest - zigmal die Sekunde aufgerufen wird. Das heißt, FullExpand muß irgend wo anders aufgerufen werden. Die Frage ist, wo?

Falls ich dich jetzt immer noch nicht verstanden habe (ich lebe schon seit fast zehn Jahren in den USA und mein Deutsch ist etwas eingerostet), dann wäre ich dir wirklich dankbar, wenn du mir mal ein kurzes Code Snippet zeigst, das nicht aus Pseudocode besteht.

Uwe

pertzschc 27. Jan 2009 21:19

Re: VirtualStringTree - FullExpand Problem
 
Zitat:

Zitat von UMOL
Ich glaube, wir reden aneinander vorbei... ;-)

Ja das ist wohl wahr.

OnGetText ist die falsche Prozedur, um mittels StringList die Daten komplett zu beschaffen. Normalerweise beschaffst Du Dir Deine Daten einmalig und hältst sie in einem ContainerObjekt (z.B. der Stringlist). Den VTV baust Du einmalig auf und weisst dabei den Nodes Objekte aus dem ContainerObjekt zu. D.h. ein Node hat die Referenz auf ein Objekt.

In OnGetText wird dann nichts anderes gemacht, als die Referenz auf das Objekt des Nodes (dessen Text bei OnGetText dargestellt werden soll) aufzulösen und dann den String mit entsprechenden Daten des Objektes zu füllen.
Beispiel:

Delphi-Quellcode:
type
  TVST_Hostlist_Node = record
    HostObj: THost;
  end;
  PVST_Hostlist_Node = ^TVST_Hostlist_Node;
Delphi-Quellcode:
function vst_Add_Host(_vst: TVirtualStringTree; _parentNode: PVirtualNode; _Host: THost): PVirtualNode;
var
  Data                                 : PVST_Hostlist_Node;
begin
  Result := _vst.AddChild(_parentNode); // Child-Node erzeugen
  _vst.ValidateNode(Result, False);    // Pointer initialisieren
  Data := _vst.GetNodeData(Result);    // Pointer auf Child-Datenbereich holen
  Data^.HostObj := _Host;
  Logger.Debug2Log('vst_Add_Host: ' + _Host.toString);
end;
Delphi-Quellcode:
procedure TForm1.VST_HostListGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: WideString);
var
  NodeData                             : PVST_Hostlist_Node;
  lHost                                : THost;
begin
  NodeData := Sender.GetNodeData(Node);
  lHost := NodeData.HostObj;
  if lHost <> nil then begin
    case Column of
      0: CellText := lHost.Hostname;
      1: CellText := lHost.Hostadress;
      2: CellText := lHost.ClientCounterStr;
      3: CellText := '';
      4: CellText := '';
    end;
  end;
end;
Gruß,
Christoph

nuclearping 27. Jan 2009 21:33

Re: VirtualStringTree - FullExpand Problem
 
Im OnGetText den Baum aufzubauen ist wirklich durchs Knie zum Auge, wie's so schön heisst. :P

UMOL 27. Jan 2009 22:12

Re: VirtualStringTree - FullExpand Problem
 
Hi Christoph,

danke, du hast mir genau *das* bestätigt, was ich schon vorher vermutet (und erwähnt) hatte: die Daten in eine Record Structure einlesen und einen entsprechenden Pointer setzen. Okay, werde ich das Ganze wohl nochmal umschreiben müssen...

Vielen Dank an dich und nuclearping für eure Hilfe und Geduld.

Uwe


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