Die Procedure CreateVstSM(sRow: String; sCol: String) wird beim Drop ausgeführt und soll mir die Zeilen und Spalten in der VST aufbauen.
In den Parameter sRow und sCol stehen jeweils die Dateiname von Listen, die die Struktur von VST beschreiben.
sRow für die Nodes, sCol für die Spalten.
Diese beiden Dateien werden in zwei TList geladen, die CreateVstSM für den Aufbau der VST benutzt.
Alle Daten sind da. Parameter gefüllt, beide TList geladen und auch die Nodes werden durchlaufen/aufgebaut.
Keine Fehlermeldung/Abbrüche beim durchlauf der Procedure. Es sollte in einem Rutsch funktionieren.
Und doch muss ich den CreateVstSM immer zweimal ausführen (Droppen), um die Zeilen und Spalten komplett aufzubauen.
1. Drop: CreateVstSM erzeugt mir nur die Spalten, obwohl er auch durch die Nodes läuft.
2. Drop: CreateVstSM baut mir nun auch die Zeilen (Nodes) dazu auf.
Was übersehe ich?
(Anmerkung: Groups: TStringArray ist nur in Vorbereitung und wird im erst zweiten Schritt gefüllt. Hier kommen dann die Berechtigung rein: WRITE)
Code: Alles auswählen
Type
  PSMData = ^TSMData;
  TSMData = record
     Key_Vater   : String;        { Key Vater-Element                                 }
     Key_Kind    : String;        { Key Kind-Element                                  }
     Bezeichnung : String;        { Bezeichnung Kind-Element                          }
     Groups      : TStringArray;  { Array für Berechtigungen                          }
  end;
...
Procedure TfMain.CreateVstSM(sRow: String; sCol: String);
var i, iCol : Integer;
    vtc : TVirtualTreeColumn;
    Data : PSMData;
    XNode: PVirtualNode;
    sVater, sKind, sBezeichnung : String;
begin
  vstSM.Clear;
  vstSM.Header.Columns.Clear;
  lGroups.LoadFromStream(sCol);
  lGroups.SortBy(tleBezeichnunmgAsc);
  lElements.LoadFromStream(sRow);
  lElements.SortBy(tleLevelAsc);
  PaintSmPanel(pSM,'-1','-1');
  vstSM.BeginUpdate;
  { erstmal alle Spalten in der VST erzeugen }
  for i := 0 to lGroups.Count do vtc := vstSM.Header.Columns.Add;
  // erste Spalte erhält die Überschrift der Nodes. Beispiel: Kostenarten-Hierarchie (sRow)
  vstSM.Header.Columns[0].Style := vsText;
  vstSM.Header.Columns[0].Options := [coAllowClick,coAllowFocus,coEnabled,coParentBidiMode,coResizable,coSmartResize,coShowDropMark,coVisible];
  vstSM.Header.Columns[0].Width:=100;
  vstSM.Header.Columns[0].Text := sRow;
  vstSM.Header.Columns[0].Tag  := i;
  // in alle weiteren Spalten werden die Benutzergruppen angelegt. Benutzergruppen (sCol)
  for i := 0 to lGroups.Count-1 do
   begin
     vstSM.Header.Columns[i+1].Style := vsText;
     vstSM.Header.Columns[i+1].Options := [coAllowClick,coAllowFocus,coEnabled,coParentBidiMode,coResizable,coSmartResize,coShowDropMark,coVisible];
     vstSM.Header.Columns[i+1].Width:=100;
     vstSM.Header.Columns[i+1].Text := lGroups.Items[i].Name_Kind;
     vstSM.Header.Columns[i+1].Tag  := i;
   end;
   vstSM.Header.Options := [hoAutoResize,hoColumnResize,hoDblClickResize,hoVisible];
   vstSM.Refresh;
   // jetzt die Hierarchie in der ersten Spalte aufbauen: Bsp.: Kostenarten-Hierarchie
   for i := 0 to lElements.Count - 1 do
   begin
     pb.Position:=i;
     sVater       := lElements.Items[i].Key_Vater;
     sKind        := lElements.Items[i].Key_Kind;
     sBezeichnung := lElements.Items[i].Bezeichnung;
     if sBezeichnung = '' then sBezeichnung := sKind;
     if sVater <> sKind then
     begin
       XNode := vstSMFindNode(sVater,vstSM.GetFirst);
       XNode := vstSM.Addchild(XNode);
     end
     else
       XNode:=vstSM.AddChild(nil);
     if xNode <> NIL then
     begin
       Data := vstSM.GetNodeData(XNode);
       vstSM.ValidateNode(XNode,false);
       if Assigned(Data) then
       begin
          Data^.Bezeichnung := sBezeichnung;
          Data^.Key_Vater   := sVater;
          Data^.Key_Kind    := sKind;
          setLength(Data^.Groups,lGroups.Count);
          for iCol := 0 to lGroups.Count do
          begin
          end;
       end;
     end;
   end;
   vstSM.EndUpdate;
   vstSM.Refresh;
end;
Function  TfMain.vstSMFindNode(s : String;StartNode: PVirtualNode): PVirtualNode;
var XNode: PVirtualNode;
    Data:  PSMData;
begin
  XNode:= StartNode;
  while XNode <> nil do
  begin
    Data := vstSM.GetNodeData(XNode);
    if Data^.Key_Kind = s then Break;
    xNode := vstSM.GetNext(XNode);
  end;
  result := XNode
end;
procedure TfMain.vstSMInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var Data : PSMData;
begin
  Data := vstSM.GetNodeData(Node);
  Data^.Key_Kind:='';
  Data^.Key_Vater:='';
  Data^.Bezeichnung:='';
  setLength(Data^.Groups,lGroups.Count);
  FillChar(Data^.Groups,SizeOf(Data^.Groups),0);
end;
procedure TfMain.vstSMGetNodeDataSize(Sender: TBaseVirtualTree;
  var NodeDataSize: Integer);
begin
  vstSM.NodeDataSize:=SizeOf(TSMData);
end;
procedure TfMain.vstSMFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var Data : PSMData;
begin
  Data := vstSM.GetNodeData(Node);
  if Assigned(Data) then
  begin
    FillChar(Data^,Sizeof(TSMData),0);
    SetLength(Data^.Groups,0);
  end;
end;
procedure TfMain.vstSMGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
var Data: PSMData;
begin
  Data := vstSM.GetNodeData(Node);
  if Column = 0 then
    CellText := Data^.Bezeichnung;
//  else
//    CellText := Data^.Groups[Column];  (noch nicht implementiert)
end;
[/codeVS. Sie erzeugt Zeilen und Spalten in der VST (so geplant).
Die Parameter sRow für die Zeilen und sCol für die Spalten werden korrekt an CreateVstSM über geben und die Prozedur wird wie geplant durchlaufen. 
Alle Daten sind da, keine Fehlermeldung, es sollte in einem Rutsch funktionieren.
[u]Leider muss ich den CreateVstSM immer zweimal ausführen, um die Zeilen und Spalten komplett aufzubauen.[/u]
1. Drop: CreateVstSM erzeugt mir [b]nur [/b]die Spalten, obwohl er auch durch die Nodes läuft.
2. Drop: CreateVstSM baut mir nun auch die Zeilen (Nodes) dazu auf.
CreateVstSM wird bei jedem Aufruf vollständig korrekt durchlaufen (inkl. Nodes). Alle Daten in den TList sind auch beim ersten Durchlauf da. Trotzdem werden die Nodes erst beim zweiten Durchlauf erzeugt.
Was übersehe ich? 
(Anmerkung: Groups: TStringArray ist nur in Vorbereitung und wird im erst zweiten Schritt gefüllt. Hier kommen dann die Berechtigung rein: WRITE)
[code]
Type
  PSMData = ^TSMData;
  TSMData = record
     Key_Vater   : String;        { Key Vater-Element                                 }
     Key_Kind    : String;        { Key Kind-Element                                  }
     Bezeichnung : String;        { Bezeichnung Kind-Element                          }
     Groups      : TStringArray;  { Array für Berechtigungen                          }
  end;
...
Procedure TfMain.CreateVstSM(sRow: String; sCol: String);
var i, iCol : Integer;
    vtc : TVirtualTreeColumn;
    Data : PSMData;
    XNode: PVirtualNode;
    sVater, sKind, sBezeichnung : String;
begin
  vstSM.Clear;
  vstSM.Header.Columns.Clear;
  lElements.LoadFromStream(sRow);
  lElements.SortBy(tleLevelAsc);
  PaintSmPanel(pSM,'-1','-1');
  vstSM.BeginUpdate;
  { erstmal alle Spalten in der VST erzeugen }
  for i := 0 to lGroups.Count do vtc := vstSM.Header.Columns.Add;
  // erste Spalte erhält die Überschrift der Nodes. Beispiel: Kostenarten-Hierarchie (sRow)
  vstSM.Header.Columns[0].Style := vsText;
  vstSM.Header.Columns[0].Options := [coAllowClick,coAllowFocus,coEnabled,coParentBidiMode,coResizable,coSmartResize,coShowDropMark,coVisible];
  vstSM.Header.Columns[0].Width:=100;
  vstSM.Header.Columns[0].Text := sRow;
  vstSM.Header.Columns[0].Tag  := i;
  // in alle weiteren Spalten werden die Benutzergruppen angelegt. Benutzergruppen (sCol)
  for i := 0 to lGroups.Count-1 do
   begin
     vstSM.Header.Columns[i+1].Style := vsText;
     vstSM.Header.Columns[i+1].Options := [coAllowClick,coAllowFocus,coEnabled,coParentBidiMode,coResizable,coSmartResize,coShowDropMark,coVisible];
     vstSM.Header.Columns[i+1].Width:=100;
     vstSM.Header.Columns[i+1].Text := lGroups.Items[i].Name_Kind;
     vstSM.Header.Columns[i+1].Tag  := i;
   end;
   vstSM.Header.Options := [hoAutoResize,hoColumnResize,hoDblClickResize,hoVisible];
   vstSM.Refresh;
   // jetzt die Hierarchie in der ersten Spalte aufbauen: Bsp.: Kostenarten-Hierarchie
   for i := 0 to lElements.Count - 1 do
   begin
     pb.Position:=i;
     sVater       := lElements.Items[i].Key_Vater;
     sKind        := lElements.Items[i].Key_Kind;
     sBezeichnung := lElements.Items[i].Bezeichnung;
     if sBezeichnung = '' then sBezeichnung := sKind;
     if sVater <> sKind then
     begin
       XNode := vstSMFindNode(sVater,vstSM.GetFirst);
       XNode := vstSM.Addchild(XNode);
     end
     else
       XNode:=vstSM.AddChild(nil);
     if xNode <> NIL then
     begin
       Data := vstSM.GetNodeData(XNode);
       vstSM.ValidateNode(XNode,false);
       if Assigned(Data) then
       begin
          Data^.Bezeichnung := sBezeichnung;
          Data^.Key_Vater   := sVater;
          Data^.Key_Kind    := sKind;
          setLength(Data^.Groups,lGroups.Count);
          for iCol := 0 to lGroups.Count do
          begin
          end;
       end;
     end;
   end;
   vstSM.EndUpdate;
   vstSM.Refresh;
end;
Function  TfMain.vstSMFindNode(s : String;StartNode: PVirtualNode): PVirtualNode;
var XNode: PVirtualNode;
    Data:  PSMData;
begin
  XNode:= StartNode;
  while XNode <> nil do
  begin
    Data := vstSM.GetNodeData(XNode);
    if Data^.Key_Kind = s then Break;
    xNode := vstSM.GetNext(XNode);
  end;
  result := XNode
end;
procedure TfMain.vstSMInitNode(Sender: TBaseVirtualTree; ParentNode,
  Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var Data : PSMData;
begin
  Data := vstSM.GetNodeData(Node);
  Data^.Key_Kind:='';
  Data^.Key_Vater:='';
  Data^.Bezeichnung:='';
  setLength(Data^.Groups,lGroups.Count);
  FillChar(Data^.Groups,SizeOf(Data^.Groups),0);
end;
procedure TfMain.vstSMGetNodeDataSize(Sender: TBaseVirtualTree;
  var NodeDataSize: Integer);
begin
  vstSM.NodeDataSize:=SizeOf(TSMData);
end;
procedure TfMain.vstSMFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var Data : PSMData;
begin
  Data := vstSM.GetNodeData(Node);
  if Assigned(Data) then
  begin
    FillChar(Data^,Sizeof(TSMData),0);
    SetLength(Data^.Groups,0);
  end;
end;
procedure TfMain.vstSMGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
var Data: PSMData;
begin
  Data := vstSM.GetNodeData(Node);
  if Column = 0 then
    CellText := Data^.Bezeichnung;
//  else
//    CellText := Data^.Groups[Column];  (noch nicht implementiert)
end;

 
  Verein
Verein 
 Links
Links Suche
Suche