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;