Einzelnen Beitrag anzeigen

Benutzerbild von NicNacMan
NicNacMan

Registriert seit: 28. Mai 2004
Ort: Hamburg
98 Beiträge
 
Delphi 2005 Personal
 
#5

Re: ListView nach VirtualStringTree

  Alt 9. Aug 2006, 00:28
Hi Onkelrossie,

da ich bald ein ähnliches Problem vor mir hab (es rückt auf meiner ToDo-List immer weiter nach unten ), hab ich mich mal dran gemacht:
(Ich hab einfach mal deine Prozedur erweitert)
Delphi-Quellcode:
procedure TForm1.LVtoVST;

  function StrCompare(s1, s2: String): Integer;
  // Liefert die Anzahl der maximal übereinstimmenden Zeichen (vom Anfang).
  var
    i, min: Integer;
  begin
    min := Length(s1);
    if (Length(s2) < min) then
      min := Length(s2);
    result := 0;
    for i := min downto 1 do
      if (Copy(s1, 1, i) = Copy(s2, 1, i)) then
      begin
        result := i;
        break;
      end;
  end;

  function FindRootNode(Caption, SubItem: String; var c0, c1: Integer): PVirtualNode;
  // Prüft, ob es schon eine Kategorie gibt, in die der Artikel rein passt.
  // c0 und c1 enthalten die Anzahl der Zeichen, die alle Untereinträge gemeinsam haben.
  var
    Node: PVirtualNode;
    Data: PTreeData;
    c: Integer;
  begin
    c0 := 0;
    result := nil;
    Node := VST.GetFirst;
    while Assigned(Node) do
    begin
      Data := VST.GetNodeData(Node);
      c := StrCompare(Caption, Data.FColumn0);
      if (c > c0) then
      begin
        c0 := c;
        c1 := StrCompare(SubItem, Data.FColumn1);
        result := Node;
      end;
      Node := VST.GetNextSibling(Node);
    end;
  end;

var
  I, c0, c1: Integer;
  TreeData: TTreeData;
  RootNode: PVirtualNode;
  Data: PTreeData;
begin
  CreateCols; //cols erstellen
  VST.NodeDataSize:= SizeOf(TTreeData); //größe zuweisen
  VST.BeginUpdate;
  for I := 0 to ListView1.Items.Count - 1 do //ListView durchlaufen, auslesen
  begin
    with TreeData do
    begin //und in den Record speichern
      FColumn0:= ListView1.Items[i].Caption;
      FColumn1:= ListView1.Items.Item[i].SubItems[0];
      FColumn2:= ListView1.Items.Item[i].SubItems[1];
      FColumn3:= ListView1.Items.Item[i].SubItems[2];
      RootNode := FindRootNode(FColumn0, FColumn1, c0, c1);
    end;
    if (RootNode = nil) then
    begin
      RootNode := AddVSTStructure(VST, nil, TreeData); // Kategorie erstellen
      AddVSTStructure(VST, RootNode, TreeData); // Artikel eintragen
    end
    else
    begin
      AddVSTStructure(VST, RootNode, TreeData); // Artikel eintrage
      Data := VST.GetNodeData(RootNode); // Überschriften anpassen
      Data.FColumn0 := Copy(Data.FColumn0, 1, c0);
      Data.FColumn1 := Copy(Data.FColumn1, 1, c1);
    end;
  end;
  VST.EndUpdate;
end;
Die Idee ist recht einfach: Vor dem eintragen, wird erst geprüft, ob es eine Kategorie gibt, in die der Artikel passt.
Falls nicht, wird erst eine erstellt, die genauso heißt.
Falls ja, werden die ersten beiden Überschriften (ist natürlich auch auf alle vier erweiterbar) so gekürzt, dass sie für alle Untereinträge passen.

lg NicNacMan
The Double-Crunch-Peanuts!
SwapIt:
  Mit Zitat antworten Zitat