unit AppsLayout;
interface
uses
Windows, Classes, SysUtils, StrUtils, Controls, Math;
type
///
/// 控制所以APP按钮的布局
///
TAppsLayout = class
private
FCol,
FRow,
FPageCount,
FPageIndex: Integer;
FClientRect: TRect;
FApps: TStringList;
FAppCountInPage: Integer;
FFirstAppRect: TRect;
FVisible: Boolean;
procedure SetClientRect(const Value: TRect);
procedure SetCol(const Value: Integer);
procedure SetPageIndex(const Value: Integer);
procedure SetRow(const Value: Integer);
procedure SetVisible(const Value: Boolean);
procedure SetAllControlCanntVisible;
///
/// 根据FCol、FRow和FClientRect,得到PageCount、首个App显示区域和单页可以显示个数
/// 如果PageCount < PageIndex, 需要重置PageIndex
///
procedure Calculate;
///
/// 更具FPageIndex显示页数
///
procedure ShowPage;
public
constructor Create;
destructor Destroy; override;
procedure AddAppBtn(AAppBtn: TControl);
procedure RemoveAppBtn(AAppBtn: TControl);
///
/// 根据首个App显示区域、FCol和FRow,布局好引用
///
procedure Layout;
property Col: Integer read FCol write SetCol;
property Row: Integer read FRow write SetRow;
property PageIndex: Integer read FPageIndex write SetPageIndex;
property ClientRect: TRect read FClientRect write SetClientRect;
property Visible: Boolean read FVisible write SetVisible;
property PageCount: Integer read FPageCount;
property Apps: TStringList read FApps;
end;
implementation
{ TAppLayout }
procedure TAppsLayout.AddAppBtn(AAppBtn: TControl);
begin
AAppBtn.Visible := False;
FApps.AddObject(IntToStr(FApps.Count), AAppBtn);
end;
procedure TAppsLayout.Calculate;
var
w, h: Integer;
begin
//如果区域没显示就不进行计算,也不进行显示
if (FClientRect.Left >= FClientRect.Right)
or (FClientRect.Top >= FClientRect.Bottom)
or (FCol <= 0)
or (FRow <= 0) then
begin
FPageCount := 0;
FPageIndex := -1;
FAppCountInPage := 0;
FFirstAppRect.Left := 0;
FFirstAppRect.Right := 0;
FFirstAppRect.Top := 0;
FFirstAppRect.Bottom := 0;
Exit;
end;
w := Round((FClientRect.Right - FClientRect.Left) div FCol);
h := Round((FClientRect.Bottom - FClientRect.Top) div FRow);
FFirstAppRect.Top := FClientRect.Top;
FFirstAppRect.Left := FClientRect.Left;
FFirstAppRect.Bottom := FFirstAppRect.Top + h;
FFirstAppRect.Right := FFirstAppRect.Left + w;
FAppCountInPage := FCol * FRow;
Layout;
end;
constructor TAppsLayout.Create;
begin
FApps := TStringList.Create;
inherited Create;
end;
destructor TAppsLayout.Destroy;
begin
FreeAndNil(FApps);
inherited;
end;
procedure TAppsLayout.Layout;
var
iLoop,
jLoop,
zLoop, iIndex : Integer;
w, h: Integer;
begin
if FApps.Count = 0 then
Exit;
FPageCount := Ceil(FApps.Count / FAppCountInPage);
if (FPageIndex < 0) and (FPageCount > 0) then
FPageIndex := 0
else
if FPageIndex >= FPageCount then
FPageIndex := FPageCount - 1;
w := FFirstAppRect.Right - FFirstAppRect.Left;
h := FFirstAppRect.Bottom - FFirstAppRect.Top;
iIndex := 0;
for zLoop := 0 to FPageCount - 1 do
for iLoop := 0 to FRow - 1 do
for jLoop := 0 to FCol - 1 do
begin
with FApps.Objects[iIndex] as TControl do
begin
Top := FFirstAppRect.Top + iLoop * h + Round((h - Height) div 2);
Left := FFirstAppRect.Left + jLoop * w + Round((w - Width) div 2);
BringToFront;
end;
if iIndex >= (FApps.Count - 1) then
begin
ShowPage;
Exit;
end;
Inc(iIndex);
end;
end;
procedure TAppsLayout.RemoveAppBtn(AAppBtn: TControl);
var
i: Integer;
begin
i := FApps.IndexOfObject(AAppBtn);
if i < 0 then
Exit;
FApps.Delete(i);
Layout;
end;
procedure TAppsLayout.SetAllControlCanntVisible;
var
iLoop: Integer;
begin
for iLoop := 0 to FApps.Count - 1 do
(FApps.Objects[iLoop] as TControl).Visible := False;
end;
procedure TAppsLayout.SetClientRect(const Value: TRect);
begin
if EqualRect(FClientRect, Value) then
Exit;
FClientRect := Value;
Calculate;
end;
procedure TAppsLayout.SetCol(const Value: Integer);
begin
if FCol = Value then
Exit;
FCol := Value;
Calculate;
end;
procedure TAppsLayout.SetPageIndex(const Value: Integer);
begin
if (Value < 0) or (Value > FPageCount - 1) then
Exit;
if Value = FPageIndex then
Exit;
FPageIndex := Value;
ShowPage;
end;
procedure TAppsLayout.SetRow(const Value: Integer);
begin
if FRow = Value then
Exit;
FRow := Value;
Calculate;
end;
procedure TAppsLayout.SetVisible(const Value: Boolean);
var
iLoop: Integer;
begin
if FVisible = Value then
Exit;
FVisible := Value;
if FVisible then
ShowPage
else
SetAllControlCanntVisible;
end;
procedure TAppsLayout.ShowPage;
var
iLoop: Integer;
begin
if (FClientRect.Left >= FClientRect.Right)
or (FClientRect.Top >= FClientRect.Bottom)
or (FCol <= 0)
or (FRow <= 0)
or (FPageIndex < 0)then
Exit;
SetAllControlCanntVisible;
for iLoop := FPageIndex * FAppCountInPage to (FPageIndex + 1) * FAppCountInPage - 1 do
begin
if iLoop > FApps.Count - 1 then
Exit;
(FApps.Objects[iLoop] as TControl).Visible := True;
(FApps.Objects[iLoop] as TControl).Invalidate;
end;
end;
end.