2011-12-05 10 views
8

Ho iniziato a giocare con il controllo TListBox, a disegnare immagini e cambiare gli stili dei font, ecc. Voglio intensificarlo un po 'e provare a manipolare di più gli oggetti con indentazione e rientro multi livello.TListbox - Manipolazione del layout di immagini e testo?

Date un'occhiata a questa immagine per una migliore idea:

enter image description here

L'idea è che gli elementi nell'elenco che si posizionano tra le voci di inizio e di fine devono essere rientrate di conseguenza.

Così, per dare un'idea Ho modificato la schermata in Paint, quindi sarebbe simile a questa:

enter image description here

Quale sarebbe il modo per avvicinarsi a questo? Il mio pensiero era quello di scorrere la lista e restituire in 2 variabili separate la quantità di articoli iniziali e finali, quindi determinare in qualche modo dove sono gli altri elementi e se la concordanza tra, ma la mia logica non è mai così buona :(

Per facilità d'uso, ho previsto di seguito il codice per mostrare come sto disegnando le immagini e gli stili:.

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls, ImgList, ComCtrls; 

type 
    TForm1 = class(TForm) 
    ImageList1: TImageList; 
    PageControl1: TPageControl; 
    TabSheet1: TTabSheet; 
    ListBox1: TListBox; 
    TabSheet2: TTabSheet; 
    ListBox2: TListBox; 
    TabSheet3: TTabSheet; 
    ListBox3: TListBox; 
    procedure FormCreate(Sender: TObject); 
    procedure ListBox1MeasureItem(Control: TWinControl; Index: Integer; 
     var Height: Integer); 
    procedure ListBox1DrawItem(Control: TWinControl; Index: Integer; 
     Rect: TRect; State: TOwnerDrawState); 
    procedure ListBox2MeasureItem(Control: TWinControl; Index: Integer; 
     var Height: Integer); 
    procedure ListBox2DrawItem(Control: TWinControl; Index: Integer; 
     Rect: TRect; State: TOwnerDrawState); 
    procedure ListBox3MeasureItem(Control: TWinControl; Index: Integer; 
     var Height: Integer); 
    procedure ListBox3DrawItem(Control: TWinControl; Index: Integer; 
     Rect: TRect; State: TOwnerDrawState); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

// assign quick identifiers to image indexes 
const 
    imgLayout  = 0; 
    imgCalculator = 1; 
    imgComment  = 2; 
    imgTime  = 3; 
    imgStart  = 4; 
    imgEnd   = 5; 

implementation 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
var 
    ListStyle: TListBoxStyle; 
begin 
    // set the listbox style here 
    ListStyle := lbOwnerDrawVariable; 
    ListBox1.Style := ListStyle; 
    ListBox2.Style := ListStyle; 
    ListBox3.Style := ListStyle; 
end; 

{******************************************************************************} 

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
var 
    TextPosition: Integer; 
    Images: TImageList; 
begin 
    TListBox(Control).Canvas.FillRect(Rect); 
    Images := ImageList1; 

    // draw the images 
    if TListBox(Control).Items.Strings[Index] = 'Layout' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout); 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Calculator' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, 
     imgCalculator); 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Comment' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgComment); 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Time' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgTime); 
    end; 

    // positions the text 
    TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight 
    (Text)) div 2; 

    // displays the text 
    TListBox(Control).Canvas.TextOut(Rect.Left + Images.Width + 8, 
    Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]); 
end; 

procedure TForm1.ListBox1MeasureItem(Control: TWinControl; Index: Integer; 
    var Height: Integer); 
begin 
    Height := ImageList1.Height; 
end; 

{******************************************************************************} 

procedure TForm1.ListBox2DrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
var 
    TextPosition: Integer; 
    Images: TImageList; 
begin 
    TListBox(Control).Canvas.FillRect(Rect); 
    Images := ImageList1; 

    // draw the images 
    if TListBox(Control).Items.Strings[Index] = 'Layout' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout); 
    TListBox(Control).Canvas.Font.Style := [fsBold]; 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Calculator' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, 
     imgCalculator); 
    TListBox(Control).Canvas.Font.Color := clBlue; 
    TListBox(Control).Canvas.Font.Style := [fsItalic]; 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Comment' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgComment); 
    TListBox(Control).Canvas.Font.Color := clRed; 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Time' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgTime); 
    end; 

    // positions the text 
    TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight 
    (Text)) div 2; 

    // displays the text 
    TListBox(Control).Canvas.TextOut(Rect.Left + Images.Width + 8, 
    Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]); 
end; 

procedure TForm1.ListBox2MeasureItem(Control: TWinControl; Index: Integer; 
    var Height: Integer); 
begin 
    Height := ImageList1.Height; 
end; 

{******************************************************************************} 

procedure TForm1.ListBox3DrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
var 
    TextPosition: Integer; 
    Images: TImageList; 
begin 
    TListBox(Control).Canvas.FillRect(Rect); 
    Images := ImageList1; 

    // draw the images 
    if TListBox(Control).Items.Strings[Index] = 'Layout' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout); 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Calculator' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, 
     imgCalculator); 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Comment' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgComment); 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Time' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgTime); 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'Start' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, 
     imgStart); 
    TListBox(Control).Canvas.Font.Style := [fsBold]; 
    end else 
    if TListBox(Control).Items.Strings[Index] = 'End' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgEnd); 
    TListBox(Control).Canvas.Font.Style := [fsBold]; 
    end; 

    // positions the text 
    TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight 
    (Text)) div 2; 

    // displays the text 
    TListBox(Control).Canvas.TextOut(Rect.Left + Images.Width + 8, 
    Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]); 
end; 

procedure TForm1.ListBox3MeasureItem(Control: TWinControl; Index: Integer; 
    var Height: Integer); 
begin 
    Height := ImageList1.Height; 
end; 

{******************************************************************************} 

end. 

Gradirei alcuni suggerimenti su come avrei potuto determinare manipolare gli elementi so di poter cambiare dove il bitmap e i testi sono posizionati, ma si sta identificando se un elemento rientra o meno tra i gruppi e se imposta il livello di rientro corretto.

Spero che questo abbia senso, ecco perché ho messo alcune immagini finte.

Grazie :)

PS, non ho mai scrivere piccoli messaggi dispiace!

AGGIORNAMENTO CON demo funzionante

ho accettato la risposta di Sertac che ho perfettamente funzionante grazie Sertac.

per aiutare gli altri che possono essere di visualizzazione - e perché ho imparato OOP voglio mostrare il mio codice per vedere se è un bene :)

ho fatto 2 unità, Lib.pas contiene le classi per gli elementi di elenco, e Unit1.pas è l'unità Form1 (i unità 1 accorciato per renderlo più chiaro per vedere cosa sta succedendo):

Lib.pas

unit Lib; 

interface 

uses 
    Classes, StdCtrls; 

type 
    TMyListData = class(TObject) 
    public 
    fCaption: string; 
    fImageIndex: integer; 
    public 
    property Caption: string read fCaption write fCaption; 
    property ImageIndex: integer read fImageIndex write fImageIndex; 

    constructor Create; 
    destructor Destroy; override; 
    end; 

type 
    TLayoutItem  = class(TMyListData); 
    TCalculatorItem = class(TMyListData); 
    TCommentItem = class(TMyListData); 
    TTimeItem  = class(TMyListData); 
    TStartItem  = class(TMyListData); 
    TEndItem  = class(TMyListData); 

const 
    imgLayout  = 0; 
    imgCalculator = 1; 
    imgComment  = 2; 
    imgTime   = 3; 
    imgStart  = 4; 
    imgEnd   = 5; 

procedure NewLayoutItem(aListBox: TListBox); 
procedure NewCalculatorItem(aListBox: TListBox); 
procedure NewCommentItem(aListBox: TListBox); 
procedure NewTimeItem(aListBox: TListBox); 
procedure NewStartItem(aListBox: TListBox); 
procedure NewEndItem(aListBox: TListBox); 
procedure DeleteItem(aListBox: TListBox; aIndex: integer); 
procedure CalculateIndents(aListBox: TListBox); 

implementation 

{ TMyListData } 

constructor TMyListData.Create; 
begin 
    inherited Create; 
end; 

destructor TMyListData.Destroy; 
begin 
    inherited; 
end; 

procedure NewLayoutItem(aListBox: TListBox); 
var 
    Obj: TLayoutItem; 
begin 
    Obj := TLayoutItem.Create; 
    try 
    Obj.Caption := 'Layout'; 
    Obj.ImageIndex := imgLayout; 

    aListBox.AddItem(Obj.Caption, Obj); 
    finally 
    Obj.Free; 
    end; 

    CalculateIndents(aListBox); 
end; 

procedure NewCalculatorItem(aListBox: TListBox); 
var 
    Obj: TCalculatorItem; 
begin 
    Obj := TCalculatorItem.Create; 
    try 
    Obj.Caption := 'Calculator'; 
    Obj.ImageIndex := imgCalculator; 

    aListBox.AddItem(Obj.Caption, Obj); 
    finally 
    Obj.Free; 
    end; 

    CalculateIndents(aListBox); 
end; 

procedure NewCommentItem(aListBox: TListBox); 
var 
    Obj: TCommentItem; 
begin 
    Obj := TCommentItem.Create; 
    try 
    Obj.Caption := 'Comment'; 
    Obj.ImageIndex := imgComment; 

    aListBox.AddItem(Obj.Caption, Obj); 
    finally 
    Obj.Free; 
    end; 

    CalculateIndents(aListBox); 
end; 

procedure NewTimeItem(aListBox: TListBox); 
var 
    Obj: TTimeItem; 
begin 
    Obj := TTimeItem.Create; 
    try 
    Obj.Caption := 'Time'; 
    Obj.ImageIndex := imgTime; 

    aListBox.AddItem(Obj.Caption, Obj); 
    finally 
    Obj.Free; 
    end; 

    CalculateIndents(aListBox); 
end; 

procedure NewStartItem(aListBox: TListBox); 
var 
    Obj: TStartItem; 
begin 
    Obj := TStartItem.Create; 
    try 
    Obj.Caption := 'Start'; 
    Obj.ImageIndex := imgStart; 

    aListBox.AddItem(Obj.Caption, Obj); 
    finally 
    Obj.Free; 
    end; 

    CalculateIndents(aListBox); 
end; 

procedure NewEndItem(aListBox: TListBox); 
var 
    Obj: TEndItem; 
begin 
    Obj := TEndItem.Create; 
    try 
    Obj.Caption := 'End'; 
    Obj.ImageIndex := imgEnd; 

    aListBox.AddItem(Obj.Caption, Obj); 
    finally 
    Obj.Free; 
    end; 

    CalculateIndents(aListBox); 
end; 


procedure DeleteItem(aListBox: TListBox; aIndex: integer); 
begin 
    aListBox.Items.Delete(aIndex); 
    aListBox.Items.Objects[aIndex] := nil; 

    CalculateIndents(aListBox); 
end; 

procedure CalculateIndents(aListBox: TListBox); 
var 
    i: Integer; 
    Indent: Integer; 
begin 
    Indent := 0; 

    for i := 0 to aListBox.Items.Count - 1 do 
    begin 
    if aListBox.Items[i] = 'End' then 
     Dec(Indent); 

    if Indent > -1 then 
     aListBox.Items.Objects[i] := Pointer(Indent); 

    if aListBox.Items[i] = 'Start' then 
     Inc(Indent); 
    end; 

    for i := aListBox.Items.Count - 1 downto 0 do 
    begin 
    if (aListBox.Items[i] = 'End') and (Indent = -1) then 
    begin 
     DeleteItem(aListBox, i); 
     Break; 
    end; 
    end; 
end; 

end. 

Unit1.pas

unit Unit1; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, StdCtrls, ImgList, ComCtrls, Buttons; 

type 
    TForm1 = class(TForm) 
    ImageList1: TImageList; 
    lbMain: TListBox; 
    btnLayout: TBitBtn; 
    btnCalculator: TBitBtn; 
    btnComment: TBitBtn; 
    btnTime: TBitBtn; 
    btnStartGroup: TBitBtn; 
    btnEndGroup: TBitBtn; 
    btnDelete: TBitBtn; 
    procedure FormCreate(Sender: TObject); 
    procedure lbMainMeasureItem(Control: TWinControl; Index: Integer; 
     var Height: Integer); 
    procedure lbMainDrawItem(Control: TWinControl; Index: Integer; 
     Rect: TRect; State: TOwnerDrawState); 
    procedure btnLayoutClick(Sender: TObject); 
    procedure btnCalculatorClick(Sender: TObject); 
    procedure btnCommentClick(Sender: TObject); 
    procedure btnTimeClick(Sender: TObject); 
    procedure btnStartGroupClick(Sender: TObject); 
    procedure btnEndGroupClick(Sender: TObject); 
    procedure btnDeleteClick(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 

uses 
    Lib; 

{$R *.dfm} 

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    // set the listbox style here 
    lbMain.Style := lbOwnerDrawVariable; 
end; 

procedure TForm1.lbMainDrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
var 
    TextPosition: Integer; 
    Images: TImageList; 
begin 
    TListBox(Control).Canvas.FillRect(Rect); 
    Images := ImageList1; 

    // draw the images 
    if TListBox(Control).Items.Strings[Index] = 'Layout' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 + 
       8 * Integer(TListBox(Control).Items.Objects[Index]), 
       Rect.Top, imgLayout); 
    end 
    else if TListBox(Control).Items.Strings[Index] = 'Calculator' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 + 
       8 * Integer(TListBox(Control).Items.Objects[Index]), 
       Rect.Top, imgCalculator); 
    end 
    else if TListBox(Control).Items.Strings[Index] = 'Comment' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 + 
       8 * Integer(TListBox(Control).Items.Objects[Index]), 
       Rect.Top, imgComment); 
    end 
    else if TListBox(Control).Items.Strings[Index] = 'Time' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 + 
       8 * Integer(TListBox(Control).Items.Objects[Index]), 
       Rect.Top, imgTime); 
    end 
    else if TListBox(Control).Items.Strings[Index] = 'Start' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 + 
       8 * Integer(TListBox(Control).Items.Objects[Index]), 
       Rect.Top, imgStart); 
    end 
    else if TListBox(Control).Items.Strings[Index] = 'End' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 + 
       8 * Integer(TListBox(Control).Items.Objects[Index]), 
       Rect.Top, imgEnd); 
    end; 

    // positions the text 
    TextPosition := (Rect.Bottom - Rect.Top - TListBox(Control).Canvas.TextHeight 
    (Text)) div 2; 

    // displays the text 
    TListBox(Control).Canvas.TextOut(
    Rect.Left + Images.Width + 8 + 8 * Longint(TListBox(Control).Items.Objects[Index]), 
    Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]); 
end; 

procedure TForm1.lbMainMeasureItem(Control: TWinControl; Index: Integer; 
    var Height: Integer); 
begin 
    Height := ImageList1.Height; 
end; 

procedure TForm1.btnLayoutClick(Sender: TObject); 
begin 
    NewLayoutItem(lbMain); 
end; 

procedure TForm1.btnCalculatorClick(Sender: TObject); 
begin 
    NewCalculatorItem(lbMain); 
end; 

procedure TForm1.btnCommentClick(Sender: TObject); 
begin 
    NewCommentItem(lbMain); 
end; 

procedure TForm1.btnTimeClick(Sender: TObject); 
begin 
    NewTimeItem(lbMain); 
end; 

procedure TForm1.btnStartGroupClick(Sender: TObject); 
begin 
    NewStartItem(lbMain); 
end; 

procedure TForm1.btnEndGroupClick(Sender: TObject); 
begin 
    NewEndItem(lbMain); 
end; 

procedure TForm1.btnDeleteClick(Sender: TObject); 
begin 
    if lbMain.ItemIndex <> -1 then 
    begin 
    DeleteItem(lbMain, lbMain.ItemIndex); 
    end; 
end; 

end. 

enter image description here

Può essere fatto meglio, vale a dire l'assegnazione degli indici di immagine in base alle Items.Objects [] di proprietà, ma questo funziona perfettamente :)

+8

Solo per curiosità, perché stai cercando di fare questo con TListBox. Questo sembra un posto perfetto per usare un TTreeView; ha un supporto integrato per il rientro, immagini basate sul tipo di contenuto e così via. Sembra che tu stia facendo un sacco di lavoro extra senza motivo. (All'inizio pensavo che tu stavi usando FireMonkey, ma una revisione del codice non indica che lo sei.) –

+0

Se vuoi un elenco di look-and-feel interamente personalizzato, puoi anche utilizzare TScrollBox e progettare i tuoi elementi su TFrames. Configura una semplice matrice gestita per gestire gli oggetti nello stesso modo di TListBox.Items (fatto facilmente), e quindi non ci sono letteralmente limiti su ciò che puoi creare. – LaKraven

+1

@KenWhite Purtroppo non ho Delphi XE2, anche io sono pienamente consapevole della Treeview che fornisce un modo migliore di visualizzare i dati come dici tu. D'altra parte, tuttavia, per una semplice visualizzazione listbox ho pensato che sarebbe stata una buona cosa provare e fare. Stavo solo sperimentando il TListbox, e dopo aver letto un po 'di più su Fire monkey dopo il tuo commento vedo che Treeview non può essere usato in quanto è un controllo di Windows, quindi fare questo con una listbox ha i suoi vantaggi in tal senso. –

risposta

6

Un modo è quello di iterare oggetti e modificare il testo per indicare il rientro:

procedure TForm1.FormCreate(Sender: TObject); 
var 
    i: Integer; 
    Indent: Integer; 
begin 

    ... 

    Indent := 0; 
    for i := 0 to ListBox3.Items.Count - 1 do begin 
    if Pos('End', ListBox3.Items[i]) > 0 then 
     Dec(Indent); 
    if Indent > 0 then 
     ListBox3.Items[i] := StringOfChar(#32, 2 * Indent) + ListBox3.Items[i]; 
    if Pos('Start', ListBox3.Items[i]) > 0 then 
     Inc(Indent); 
    end; 
end; 

Dal testo oggetti sono cambiati, questo approccio richiede di verificare il testo di conseguenza al momento dell'elaborazione:

procedure TForm1.ListBox3DrawItem(Control: TWinControl; Index: Integer; 
    Rect: TRect; State: TOwnerDrawState); 
var 
    TextPosition: Integer; 
    Images: TImageList; 
begin 
    TListBox(Control).Canvas.FillRect(Rect); 
    Images := ImageList1; 

    // draw the images 
    if Pos('Layout', TListBox(Control).Items.Strings[Index]) > 0 then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4, Rect.Top, imgLayout); 
    end else 
    if Pos('Calculator', TListBox(Control).Items.Strings[Index]) > 0 then 
    .. 

(Con questo approccio, il rientro immagini sarebbe un po 'di lavoro, contare gli spazi iniziali in una nota di testo, e così via ..)


Se obj articoli gli ects non sono già utilizzati, un approccio leggermente migliore può essere quello di memorizzare il rientro come un numero intero e utilizzarlo durante il disegno. Per esempio. quando l'iterazione:

Indent := 0; 
for i := 0 to ListBox3.Items.Count - 1 do begin 
    if ListBox3.Items[i] = 'Start' then 
    Inc(Indent); 
    ListBox3.Items.Objects[i] := Pointer(Indent); 
    if ListBox3.Items[i] = 'End' then 
    Dec(Indent); 
end; 

Quando si disegna:

.. 
    if TListBox(Control).Items.Strings[Index] = 'Layout' then 
    begin 
    Images.Draw(TListBox(Control).Canvas, Rect.Left + 4 + 
       8 * Integer(TListBox(Control).Items.Objects[Index]), 
       Rect.Top, imgLayout); 

    .. 
    // displays the text 
    TListBox(Control).Canvas.TextOut(
    Rect.Left + Images.Width + 8 + 8 * Longint(TListBox(Control).Items.Objects[Index]), 
    Rect.Top + TextPosition, TListBox(Control).Items.Strings[index]); 
    .. 
+1

+1, non ho ancora visto tutto il codice, ma memorizzare il valore del rientro come puntatore a ciascun elemento è una buona idea per i nuovi elementi. Consentitemi di guardare oltre il resto del codice grazie Sertac ... –

+0

@Craig -> * "nuovi elementi" *> L'aggiunta va bene, ma quando si inserisce, iterando gli elementi dopo la posizione di inserimento sarebbe richiesto. –

+0

Sto scrivendo una demo basata sulle informazioni che mi hai fornito (mentre sto imparando OOP posso vedere cosa ne pensano gli esperti del codice degli oggetti :) rimani sintonizzato .. –

3

Penso che probabilmente si dovrebbe utilizzare il TTreeView invece, che supporta già il rientro degli oggetti secondari.

Per rispondere alla tua domanda, penso che potresti utilizzare la ricorsione per disegnare gli elementi nel tuo TListBox. Usando la ricorsione, è facile vedere quanti livelli sono profondi.

Ecco come funziona la maggior parte dei parser, come i parser HTML.

Ecco alcuni pseudo codice che illustra il concetto:

procedure DrawBranch(branch: TMyList; indent: Integer); 
var 
    i: Integer; 
begin 
    // Draw the current branch, using the indent value 
    branch.Draw; 
    // Iterate through all of the child branches 
    for i := 0 to branch.Children.Count - 1 do 
    begin 
    // Each time we recurse further, we add 1 to the indent 
    DrawBranch(branch.Child[i], indent + 1); 
    end; 
end; 

procedure DrawTree; 
begin 
    // Start the whole thing off with the root branch 
    // We start the indent at 0 
    DrawBranch(root, 0); 
end; 

si vorrà un nodo radice "nascosto" nel tuo caso.

Utilizzerai la stessa logica per aggiungere i tuoi articoli a un TTreeView.

Problemi correlati