2012-11-04 22 views
6

Sto cercando un'implementazione di TFlowPanel (o simile) che funzionerà con D5.
Fondamentalmente ho bisogno del TFlowPanel per lavorare all'interno di un TScrollBox (con barra di scorrimento verticale), quindi i controlli si riavvolgeranno in base alla larghezza di quello TScrollBox.TFlowPanel in D5

Le immagini mostrano in pratica quello che mi serve:

enter image description here

Dopo aver ridimensionato i controlli vengono riposizionati automaticamente:

enter image description here

Con barra di scorrimento verticale:

enter image description here

+1

Dovrebbe essere abbastanza facile da compilare, soprattutto se si ha il codice del FlowPanel delle versioni successive. Ma se l'avessi fatto, non avrei potuto testarlo in D5. : -/ – GolezTrol

risposta

8

Solo un concetto. Nessun vari FlowTypes e nessuna possibilità di modificare l'ordine dei controlli. Potresti comunque spostarli cambiando l'ordine nel DFM, penso, o resettando il genitore.

Il pannello misura verticalmente per adattarsi a tutti i comandi. Ciò significa che quando lo metti in una scrollbox funzionerà automaticamente.

unit uAlignPanel; 

interface 

uses 
    Windows, SysUtils, Classes, Controls, ExtCtrls; 

type 
    TAlignPanel = class(TPanel) 
    protected 
    procedure SetChildOrder(Child: TComponent; Order: Integer); overload; override; 
    procedure SetZOrder(TopMost: Boolean); override; 
    public 
    procedure AlignControls(AControl: TControl; var Rect: TRect); override; 
    procedure Insert(AControl: TControl); 
    procedure Append(AControl: TControl); 
    function GetChildOrder(Child: TControl): Integer; 
    procedure SetChildOrder(Child: TControl; Order: Integer); reintroduce; overload; virtual; 
    procedure MoveChildBefore(Child: TControl; Sibling: TControl); virtual; 
    end; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterComponents('StackOverflow', [TAlignPanel]); 
end; 

{ TAlignPanel } 

procedure TAlignPanel.AlignControls(AControl: TControl; var Rect: TRect); 
var 
    i: Integer; 
    x, y: Integer; 
    LineHeight: Integer; 
begin 
    x := 0; y := 0; 
    LineHeight := 0; 
    for i := 0 to ControlCount - 1 do 
    begin 
    if x + Controls[i].Width > ClientWidth then 
    begin 
     x := 0; 
     y := y + LineHeight; 
     LineHeight := 0; 
    end; 
    Controls[i].Top := y; 
    Controls[i].Left := x; 
    x := x + Controls[i].Width; 
    if Controls[i].Height > LineHeight then 
     LineHeight := Controls[i].Height; 
    end; 

    // Height + 1. Not only looks nices, but also prevents a small redrawing 
    // problem of the bottom line of the panel when adding controls. 
    ClientHeight := y + LineHeight + 1; 

end; 

procedure TAlignPanel.Append(AControl: TControl); 
begin 
    AControl.Parent := Self; 
    AControl.BringToFront; 
    Realign; 
end; 

function TAlignPanel.GetChildOrder(Child: TControl): Integer; 
begin 
    for Result := 0 to ControlCount - 1 do 
    if Controls[Result] = Child then 
     Exit; 
    Result := -1; 
end; 

procedure TAlignPanel.Insert(AControl: TControl); 
begin 
    AControl.Parent := Self; 
    AControl.SendToBack; 
    Realign; 
end; 

procedure TAlignPanel.MoveChildBefore(Child, Sibling: TControl); 
var 
    CurrentIndex: Integer; 
    NewIndex: Integer; 
begin 
    if Child = Sibling then 
    raise Exception.Create('Child and sibling cannot be the same'); 

    CurrentIndex := GetChildOrder(Child); 
    if CurrentIndex = -1 then 
    raise Exception.CreateFmt('Control ''%s'' is not a child of panel ''%s''', 
           [Sibling.Name, Name]); 

    if Sibling <> nil then 
    begin 
    NewIndex := GetChildOrder(Sibling); 
    if NewIndex = -1 then 
     raise Exception.CreateFmt('Sibling ''%s'' is not a child of panel ''%s''', 
           [Sibling.Name, Name]); 
    if CurrentIndex < NewIndex then 
     Dec(NewIndex); 
    end 
    else 
    NewIndex := ControlCount; 

    SetChildOrder(Child, NewIndex); 
end; 

procedure TAlignPanel.SetChildOrder(Child: TComponent; Order: Integer); 
begin 
    inherited; 
    Realign; 
end; 

procedure TAlignPanel.SetChildOrder(Child: TControl; Order: Integer); 
begin 
    SetChildOrder(TComponent(Child), Order); 
end; 

procedure TAlignPanel.SetZOrder(TopMost: Boolean); 
begin 
    inherited; 
    Realign; 
end; 

end. 
+1

Anche 'BringToFront' potrebbe funzionare (per quanto riguarda lo spostamento dei controlli). –

+0

Per fare cosa? I controlli non si sovrappongono. – GolezTrol

+0

Non l'ho verificato, ma avevo l'impressione che 'BringToFront' cambi l'ordine dei controlli nella proprietà' Controls'. Almeno, 'BringToFront' sembrava funzionare per me quando lo usavo su un gruppo di controlli allineati allo stesso modo (cioè tutti allineati in alto, o tutti allineati a sinistra ecc.). –