Мне нужна моя форма в Delphi для изменения размера, и все компоненты и элементы управления должны растягиваться пропорционально, а также размер шрифта и т. Д. Сейчас, чтобы изменить размер компонентов, я пишу код внутри события OnResize и вручную вычисляю все компоненты, размеров и шрифтов. Я хотел бы иметь более простое решение, которое я могу применить к различным приложениям, не переписывая этот код для каждой формы. Я нашел некоторые компоненты в Интернете, но они являются условно-бесплатными. Вы можете что-то предложить?Что представляет собой лучший бесплатный способ внести изменения в форму в Delphi 7?
ответ
Вы можете использовать мой компонент TArtPercentageWireGrid. Я использовал его в течение многих лет. Оставьте его на форме, поместите любой компонент, который вам нравится, а затем, когда вы измените размер формы, контур компонента будет пропорционально изменяться. Брайан
unit UArtWireGrids;
interface
uses
Windows,
Messages,
SysUtils,
Classes,
Graphics,
Controls,
Forms,
Dialogs;
type
float = double;
TFloatPoint = record X, Y : float end;
TFloatRect = record
case Integer of
0: (Left, Top, Right, Bottom: float);
1: (TopLeft, BottomRight: TFloatPoint);
end;
TARTSimpleWireGrid = class(TGraphicControl)
private
{ Private declarations }
FGridSpacing : integer;
FPen : TPen;
FBrush : TBrush;
procedure SetGridSpacing(AValue : integer);
procedure SetBrush(AValue : TBrush);
procedure SetPen(AValue : TPen);
protected
{ Protected declarations }
procedure Paint; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
property Align;
property Brush : TBrush read FBrush write SetBrush;
property Pen : TPen read FPen write SetPen;
property GridSpacing : integer read FGridSpacing write SetGridSpacing;
procedure StyleChanged(Sender : TObject);
property Visible;
end;
TGridStyle = (gsLines, gsPoints);
TARTPercentageWireGrid = class(TGraphicControl)
private
{ Private declarations }
FLineSpacing : double;
FPen : TPen;
FBrush : TBrush;
FGridVisible : boolean;
FGridStyle : TGridStyle;
procedure SetLineSpacing(AValue : double);
procedure SetBrush(AValue : TBrush);
procedure SetPen(AValue : TPen);
function GetLineSpacingPixelX : integer;
function GetLineSpacingPixelY : integer;
procedure SetGridVisible(AState : boolean);
procedure SetGridStyle(AValue : TGridStyle);
function RoundToGrid(AValue : float) : float;
protected
{ Protected declarations }
procedure Paint; override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure DrawPointsOnCanvas(ACanvas : TCanvas);
function GridXToPixel(const AGridX : float) : integer;
function GridYToPixel(const AGridY : float) : integer;
function GridPointToPixel(const APoint : TFloatPoint) : TPoint;
function GridRectToPixel(const ARect : TFloatRect) : TRect;
function PixelXToGrid(AValue : integer) : float;
function PixelYToGrid(AValue : integer) : float;
function PixelPointToGrid(const APoint : TPoint) : TFloatPoint;
function PixelRectToGrid(const ARect : TRect) : TFloatRect;
function GridAlignPixelX(AValue : integer) : integer;
function GridAlignPixelY(AValue : integer) : integer;
function GridAlignPixelPoint(const APoint : TPoint) : TPoint;
function GridAlignPixelRect(const ARect : TRect) : TRect;
function MoveGridRect(const ARect : TFloatRect;
const ADeltaX, ADeltaY : float) : TFloatRect;
function ScaleGridRect(const ARect : TFloatRect;
const AScale : float) : TFloatRect;
function GridLineXToPixel(AValue : integer) : integer;
function GridLineYToPixel(AValue : integer) : integer;
function GridLinePointToPixel(const APoint : TPoint) : TPoint;
function GridLineRectToPixel(const ARect : TRect) : TRect;
function PixelXToGridLine(AValue : integer) : integer;
function PixelYToGridLine(AValue : integer) : integer;
function PixelPointToGridLine(const APoint : TPoint) : TPoint;
function PixelRectToGridLine(const ARect : TRect) : TRect;
published
{ Published declarations }
property Align;
property Brush : TBrush read FBrush write SetBrush;
property Pen : TPen read FPen write SetPen;
property LineSpacing : double read FLineSpacing write SetLineSpacing;
property LineSpacingPixelX : integer read GetLineSpacingPixelX;
property LineSpacingPixelY : integer read GetLineSpacingPixelY;
procedure StyleChanged(Sender : TObject);
property Visible;
property GridVisible : boolean read FGridVisible write SetGridVisible;
property GridStyle : TGridStyle read FGridStyle write SetGridSTyle;
end;
implementation
{TARTSimpleWireGrid}
{ ---------------------------------------------------------------------------- }
constructor TARTSimpleWireGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FPen := TPen.Create;
FPen.OnChange := StyleChanged;
FBrush := TBrush.Create;
FBrush.OnChange := StyleChanged;
GridSpacing := 20;
Height := 100;
Width := 100;
end;
destructor TARTSimpleWireGrid.Destroy;
begin
FPen.Free;
FBrush.Free;
Inherited Destroy;
end;
procedure TARTSimplewireGrid.SetGridSpacing(AValue : integer);
begin
If AValue <> FGridSpacing then
begin
FGridSpacing := AValue;
Invalidate;
end;
end;
procedure TARTsimpleWireGrid.Paint;
var
I : integer;
begin
Inherited Paint;
If FGridspacing < 20 then
GridSpacing := 20;
Canvas.Brush.Assign(FBrush);
Canvas.Pen.Assign(FPen);
// Vertical bars
I := 0;
While I < ClientWidth do
begin
Canvas.MoveTo(I,0);
Canvas.LineTo(I,ClientHeight);
Inc(I,FGridSpacing);
end;
// Horiz bars
I := 0;
While I < ClientHeight do
begin
Canvas.MoveTo(0,I);
Canvas.LineTo(ClientWidth,I);
Inc(I,FGridSpacing);
end;
end;
procedure TARTSimplewireGrid.SetBrush(AValue : TBrush);
begin
FBrush.Assign(AValue);
end;
procedure TARTSimplewireGrid.SetPen(AValue : TPen);
begin
FPen.Assign(AValue);
end;
procedure TARTSimplewireGrid.StyleChanged(Sender : TObject);
begin
Invalidate;
end;
//End TARTSimpleWireGrid
end.
{TARTPercentageWireGrid}
{ ---------------------------------------------------------------------------- }
constructor TARTPercentageWireGrid.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
If AOwner is TForm then
begin
OnMouseDown := Tform(AOwner).OnMouseDown;
OnMouseUp := Tform(AOwner).OnMouseUp;
OnMouseMove := Tform(AOwner).OnMouseMove;
end;
FPen := TPen.Create;
FPen.OnChange := StyleChanged;
FBrush := TBrush.Create;
FBrush.OnChange := StyleChanged;
FGridVisible := True;
LineSpacing := 10;
Height := 100;
Width := 100;
end;
destructor TARTPercentageWireGrid.Destroy;
begin
FPen.Free;
FBrush.Free;
Inherited Destroy;
end;
procedure TARTPercentagewireGrid.SetLineSpacing(AValue : double);
begin
If AValue <> FLineSpacing then
begin
FLineSpacing := AValue;
If FLineSpacing < 1.0 then
FLineSpacing := 1.0;
Invalidate;
end;
end;
procedure TARTPercentagewireGrid.DrawPointsOnCanvas(ACanvas : TCanvas);
var
X, Y : integer;
FX, FY : float;
begin
FY := 0.0;
Repeat
FY := FY + FLineSpacing;
FX := 0.0;
Y := GridYToPixel(FY);
Repeat
FX := FX + FLineSpacing;
X := GridXToPixel(FX);
ACanvas.Pixels[ X, Y ] := clBlack;
until FX >= 100;
until FY >= 100;
end;
procedure TARTPercentageWireGrid.Paint;
procedure DrawLines;
procedure LinesVert;
var
X : integer;
F : double;
begin
F := 0.0;
Repeat
F := F + FLineSpacing;
X := GridXToPixel(F);
Canvas.MoveTo(X, 0);
Canvas.LineTo(X, Height);
until X >= ClientWidth;
end;
procedure LinesHorz;
var
F : double;
Y : integer;
begin
F := 0.0;
Repeat
F := F + FLineSpacing;
Y := GridYToPixel(F);
Canvas.MoveTo(0, Y);
Canvas.LineTo(Width, Y);
until Y >= ClientHeight;
end;
begin
LinesVert;
LinesHorz;
end;
begin
Inherited Paint;
If FGridVisible then
begin
Canvas.Brush.Assign(FBrush);
Canvas.Pen.Assign(FPen);
Case FGridStyle of
gsLines : DrawLines;
gsPoints : DrawPointsOnCanvas(Canvas);
end;
end;
end;
procedure TARTPercentagewireGrid.SetBrush(AValue : TBrush);
begin
FBrush.Assign(AValue);
end;
procedure TARTPercentagewireGrid.SetPen(AValue : TPen);
begin
FPen.Assign(AValue);
end;
procedure TARTPercentagewireGrid.StyleChanged(Sender : TObject);
begin
Invalidate;
end;
function TARTPercentageWireGrid.GridXToPixel(const AGridX : float) : integer;
begin
Result := Round(AGridX * Width/100);
end;
function TARTPercentageWireGrid.GridYToPixel(const AGridY : float) : integer;
begin
Result := Round(AGridY * Height/100);
end;
function TARTPercentageWireGrid.GetLineSpacingPixelX : integer;
begin
Result := GridXToPixel(FLineSpacing);
end;
function TARTPercentageWireGrid.GetLineSpacingPixelY : integer;
begin
Result := GridYToPixel(FLineSpacing);
end;
function TARTPercentageWireGrid.GridPointToPixel(const APoint : TFloatPoint) : TPoint;
begin
Result.X := GridXToPixel(APoint.X);
Result.Y := GridYToPixel(APoint.Y);
end;
function TARTPercentageWireGrid.GridRectToPixel(const ARect : TFloatRect) : TRect;
begin
Result.TopLeft := GridPointToPixel(ARect.TopLeft);
Result.BottomRight := GridPointToPixel(ARect.BottomRight);
end;
function TARTPercentageWireGrid.PixelXToGrid(AValue : integer) : float;
begin
Result := (Trunc(AValue) * 100)/Width;
end;
function TARTPercentageWireGrid.PixelYToGrid(AValue : integer) : float;
begin
Result := (Trunc(AValue) * 100)/Height;
end;
function TARTPercentageWireGrid.PixelPointToGrid(const APoint : TPoint) : TFloatPoint;
begin
Result.X := PixelXToGrid(APoint.X);
Result.Y := PixelYToGrid(APoint.Y);
end;
function TARTPercentageWireGrid.PixelRectToGrid(const ARect : TRect) : TFloatRect;
begin
Result.TopLeft := PixelPointToGrid(ARect.TopLeft);
Result.BottomRight := PixelPointToGrid(ARect.BottomRight);
end;
function TARTPercentageWireGrid.RoundToGrid(AValue : float) : float;
begin
Result := LineSpacing * Round(AValue/LineSpacing);
end;
function TARTPercentageWireGrid.GridAlignPixelX(AValue : integer) : integer;
begin
Result := GridXToPixel(RoundToGrid(PixelXToGrid(AValue)));
end;
function TARTPercentageWireGrid.GridAlignPixelY(AValue : integer) : integer;
begin
Result := GridYToPixel(RoundToGrid(PixelYToGrid(AValue)));
end;
function TARTPercentageWireGrid.GridAlignPixelPoint(const APoint : TPoint) : TPoint;
begin
Result.X := GridAlignPixelX(APoint.X);
Result.Y := GridAlignPixelY(APoint.Y);
end;
function TARTPercentageWireGrid.GridAlignPixelRect(const ARect : TRect) : TRect;
begin
Result.TopLeft := GridAlignPixelPoint(ARect.TopLeft);
Result.BottomRight := GridAlignPixelPoint(ARect.BottomRight);
// Its possible that aligning may have collapsed a width or height to
// zero. If so, make it at least 1 unit in size
If Result.Top = Result.Bottom then
Result.Bottom := Result.Top + LineSpacingPixelY;
If Result.Left = Result.Right then
Result.Right := Result.Left + LineSpacingPixelX;
end;
procedure TARTPercentageWireGrid.SetGridVisible(AState : boolean);
begin
If AState <> FGridVisible then
begin
FGridVisible := AState;
Invalidate;
end;
end;
function TARTPercentageWireGrid.MoveGridRect(const ARect : TFloatRect;
const ADeltaX, ADeltaY : float) : TFloatRect;
begin
Result.Left := ARect.Left + ADeltaX;
Result.right := ARect.Right + ADeltaX;
Result.Top := ARect.Top + ADeltaY;
Result.Bottom := ARect.Bottom + ADeltaY;
end;
function TARTPercentageWireGrid.ScaleGridRect(const ARect : TFloatRect;
const AScale : float) : TFloatRect;
begin
Result.Left := ARect.Left * AScale;
Result.right := ARect.Right * Ascale;
Result.Top := ARect.Top * AScale;
Result.Bottom := ARect.Bottom * AScale;
end;
procedure TARTPercentageWireGrid.SetGridStyle(AValue : TGridStyle);
begin
If AValue <> FGridStyle then
begin
FGridStyle := AValue;
Invalidate;
end;
end;
function TARTPercentageWireGrid.GridLineXToPixel(AValue : integer) : integer;
begin
Result := GridXToPixel(Trunc(AValue) * LineSpacing);
end;
function TARTPercentageWireGrid.GridLineYToPixel(AValue : integer) : integer;
begin
Result := GridYToPixel(Trunc(AValue) * LineSpacing);
end;
function TARTPercentageWireGrid.GridLinePointToPixel(const APoint : TPoint) : TPoint;
begin
Result.X := GridLineXToPixel(APoint.X);
Result.Y := GridLineYToPixel(APoint.Y);
end;
function TARTPercentageWireGrid.GridLineRectToPixel(const ARect : TRect) : TRect;
begin
Result.TopLeft := GridLinePointToPixel(ARect.TopLeft);
Result.BottomRight := GridLinePointToPixel(ARect.BottomRight);
end;
function TARTPercentageWireGrid.PixelXToGridLine(AValue : integer) : integer;
begin
Result := Round(PixelXToGrid(AValue)/FLineSpacing);
end;
function TARTPercentageWireGrid.PixelYToGridLine(AValue : integer) : integer;
begin
Result := Round(PixelYToGrid(AValue)/FLineSpacing);
end;
function TARTPercentageWireGrid.PixelPointToGridLine(const APoint : TPoint) : TPoint;
begin
Result.X := PixelXToGridLine(APoint.X);
Result.Y := PixelYToGridLine(APoint.Y);
end;
function TARTPercentageWireGrid.PixelRectToGridLine(const ARect : TRect) : TRect;
begin
Result.TopLeft := PixelPointToGridLine(ARect.TopLeft);
Result.BottomRight := PixelPointToGridLine(ARect.BottomRight);
end;
{End TARTPercentageWireGrid}
{ ---------------------------------------------------------------------------- }
Подробнее:
@Ulrich и другие: Я сожалею, я уже забыл пару вещей. Простой пример следующим образом:
Получить работу сетки - установить его Align = alClient и при изменении размеров формы вы должны увидеть сетки размера с ним.
Объявляет следующий вид: PRIVATE поле
FBounds: массив TFloatRect;
Предположим, вам нужна только одна кнопка с размерами «Button1». Поместите в FormCreate следующее:
SetLength (FBounds, 1); FBounds [0]: = ARTPercentageWireGrid1.PixelRectToGrid (Button1.BoundsRect);
Наконец, поместите в FormResize:
Button1.BoundsRect: = ARTPercentageWireGrid1.GridRectToPixel (FBounds [0]);
При изменении размера формы кнопка будет отслеживать форму пропорционально. Для работы со всеми контролями:
procedure TForm1.FormResize(Sender: TObject);
var
I : integer;
begin
//Button1.BoundsRect := ARTPercentageWireGrid1.GridRectToPixel(FBounds[0]);
For I := 0 to ComponentCount-1 do
If Components[I] is TControl then
With Components[I] as TControl do
If Align <> alClient then
BoundsRect := ARTPercentageWireGrid1.GridRectToPixel(FBounds[I]);
end;
procedure TForm1.FormCreate(Sender: TObject);
var
I : integer;
begin
//SetLength(FBounds, 1);
//FBounds[0] := ARTPercentageWireGrid1.PixelRectToGrid(Button1.BoundsRect);
SetLength(FBounds, ComponentCount);
For I := 0 to ComponentCount-1 do
If Components[I] is TControl then
With Components[I] as TControl do
If Align <> alClient then
FBounds[I] := ARTPercentageWireGrid1.PixelRectToGrid(BoundsRect);
end;
Извинения для лоскутной коды. Брайан.
Вы можете использовать свойство Anchor для каждого элемента управления. Это позволяет вам «привязать» стороны элемента управления к определенной стороне формы.
Например, если вы хотите, чтобы TMemo заполнил середину формы при ее изменении, установите значение Anchor
на [akLeft,akTop,akRight,akBottom]
. Или, если вы хотите, чтобы кнопка соответствовала нижней части формы при ее изменении, установите для свойства Anchor
значение [akLeft,akBottom]
+1 но это не будет * растягивать * размер шрифта. –
И я думаю, что это тоже не изменит размеры компонентов. –
Он изменит размеры компонентов, но вы оба правы, это не совсем то, что задается ... Это не изменяет размер шрифтов. Я уйду на пенсию, чтобы рассмотреть лучший ответ! – Nat
Если вы довольны кодом, который вы использовали в событии OnResize, может быть полезно создать собственные пользовательские компоненты, включающие этот код. Это упростит будущее использование этих компонентов.
Я не знаю, как это сделать, в коде я вручную вводим координаты и размеры каждого компонента. Как эта функция автоматически настраивается в любой форме? –
точно ... создайте настраиваемый компонент, который наследует TForm, и все формы должны наследовать компонент. И поместите код из события OnResize в метод, например ResizeControls. Проблема заключается в том, как автоматически вызывать этот метод при возникновении события OnResize. Вернемся к вам по этому вопросу: D Или сделайте это не изящным способом и для каждой формы в OnResize вызовите метод. – AlexRednic
Я до сих пор не вижу, как компонент поймет, какие координаты он должен поместить для всех элементов управления в форме. В идеале я хотел бы, чтобы он занимал время и размер времени проектирования и пропорционально менял его всякий раз, когда изменяется размер формы. –
Check ResizeKit Компонент для Delphi. Он может изменять размеры компонентов и шрифтов.
Существует бесплатная пробная версия.
Полезный блок кода (после того, как все изменения были внесены), но, поскольку он отправлен сейчас 3 года спустя, он не работает, поскольку компонент не зарегистрирован. Вам нужно будет добавить следующий код в инструкции implementation
в блоке, прежде чем вы сможете добавить компонент.
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('ComponentName', [TARTPercentageWireGrid]);
end;
использует UArtDefs, можете ли вы предложить, где я могу это получить? –
@Tofig: Удалить UArtDefs и добавить следующее: 'float = Single; TFloatPoint = запись x, y: float; конец; TFloatRect = запись case Integer 0: (Слева, Верх, Вправо, Внизу: поплавок); 1: (TopLeft, BottomRight: TFloatPoint); конец; '. По крайней мере, это компилируется. :-) –
@Brian: Я сделал простое тестовое приложение (создав TARTPercentageWireGrid в конструкторе формы), но элементы управления в форме не изменяются. Как это должно работать? –