2012-11-04 13 views
6

Poszukuję implementacji TFlowPanel (lub podobnej), która będzie działać z D5.
Zasadniczo potrzebuję TFlowPanel do pracy wewnątrz TScrollBox (z pionowym paskiem przewijania), aby elementy sterujące były zawijane w oparciu o szerokość tego TScrollBox.TFlowPanel podobnie w D5

The obrazów zasadzie pokazać to, czego potrzebuję:

enter image description here

Po zmianie rozmiaru kontrole są automatycznie przeniesiony:

enter image description here

z pionowym pasku przewijania:

enter image description here

+1

Powinno być całkiem łatwe do zbudowania, zwłaszcza jeśli otrzymałeś kod FlowPanel z późniejszych wersji. Ale jeśli tak, nie mogłem go przetestować w D5. : -/ – GolezTrol

Odpowiedz

8

Tylko koncepcja. Brak różnych typów FlowTypes i brak możliwości zmiany kolejności elementów sterujących. Nadal można je przenosić, zmieniając kolejność w DFM, lub resetując rodzica.

Wielkość panelu w pionie w celu dopasowania do wszystkich elementów sterujących. Oznacza to, że kiedy umieścisz go w przewijanym polu, zadziała automatycznie.

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

'BringToFront' może również działać (w odniesieniu do przenoszenia kontrolek). –

+0

Co robić? Kontrolki się nie nakładają. – GolezTrol

+0

Nie sprawdziłem tego, ale miałem wrażenie, że 'BringToFront' zmienia kolejność elementów sterujących we właściwości' Controls'. Przynajmniej "BringToFront" wydawało się działać dla mnie, gdy użyłem go w grupie kontrolek ułożonych w ten sam sposób (tj. Wszystkie wyrównane do góry lub wszystkie wyrównane do lewej itd.). –