2012-12-30 74 views
2

如何創建約束比例 TControl(在我的情況TGraphicControl)?
所以,如果我改變它的Width - Height將改變比例(反之亦然)。
此外,如果我設置BoundsRect控件應保持比例。 在我控制我有一個AspectRatio: TPoint屬性,設置:TControl約束比例

AspectRatio.X := 4; 
AspectRatio.Y := 3; 

所以現在我AspectRatioFactor = 4/3。這個比例應該始終保持。

這怎麼辦?

回答

6
unit Unit1; 

interface 

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

type 
    TPanel = Class(ExtCtrls.TPanel) 
    private 
    FAspectRatio: TPoint; 
    procedure SetAspectRatio(const Value: TPoint); 
    public 
    constructor Create(AOwner: TComponent); override; 
    procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; 
    property AspectRatio: TPoint read FAspectRatio write SetAspectRatio; 
    end; 

    TForm1 = class(TForm) 
    Panel1: TPanel; 
    Button1: TButton; 
    Button2: TButton; 
    Button3: TButton; 
    procedure Button1Click(Sender: TObject); 
    procedure Button2Click(Sender: TObject); 
    procedure Button3Click(Sender: TObject); 
    end; 

var 
    Form1: TForm1; 

implementation 

{$R *.dfm} 
{ TPanel } 

constructor TPanel.Create(AOwner: TComponent); 
begin 
    inherited; 
    FAspectRatio.X := 4; 
    FAspectRatio.Y := 3; 
end; 

procedure TPanel.SetAspectRatio(const Value: TPoint); 
begin 
    FAspectRatio := Value; 
    AdjustSize; 
end; 

procedure TPanel.SetBounds(ALeft, ATop, AWidth, AHeight: Integer); 
var 
    vh: Double; 
begin 
    if FAspectRatio.Y <> 0 then 
    begin 
    vh := FAspectRatio.X/FAspectRatio.Y; 
    if Round(AHeight * vh) <> AWidth then 
    begin 
     if AWidth <> Width then 
     AHeight := Round(AWidth/vh) 
     else 
     AWidth := Round(AHeight * vh); 
    end; 
    end; 
    inherited; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
begin 
    Panel1.Width := 101; 
end; 

procedure TForm1.Button2Click(Sender: TObject); 
begin 
    Panel1.Height := 101; 
end; 

procedure TForm1.Button3Click(Sender: TObject); 
var 
    p: TPoint; 
begin 
    p.X := 5; 
    p.Y := 3; 
    Panel1.AspectRatio := p; 
end; 

end. 

覆蓋Setbounds將確保給定的AspectRatio得到維護。
AspectRatio的Setter中的AdjustSize將確保一次應用AspectRatio的更改。
按鈕事件僅用於演示。

+0

你應該避免在這裏使用浮點運算。用'MulDiv'很容易做到。否則這個做得很好。 +1 –

+5

@DavidHeffernan謝謝,我在完成我的工作後在您的帖子中看到了它。我現在不會改變它,所以兩者可以相反地看到。您的評論將帶領其他讀者。 – bummi

+1

那麼,這裏發生了什麼?沒有文字描述解決方案。哪一部分對答案至關重要,哪一部分只是說明它的工作原理?它是如何工作的? –

4

覆蓋在控制的CanResize虛擬方法:

function TMyControl.CanResize(var NewWidth, NewHeight: Integer): Boolean; 
begin 
    NewHeight := MulDiv(NewWidth, AspectRatio.Y, AspectRatio.X); 
    Result := True; 
end; 

這使得寬度是主尺寸。如果你想讓身高負責,那麼你可以重新安排公式。

您可以嘗試在選擇哪個維度是主數據時很聰明。

function TMyControl.CanResize(var NewWidth, NewHeight: Integer): Boolean; 
begin 
    if abs(NewWidth-Width)>abs(NewHeight-Height) then 
    NewHeight := MulDiv(NewWidth, AspectRatio.Y, AspectRatio.X) 
    else 
    NewWidth := MulDiv(NewHeight, AspectRatio.X, AspectRatio.Y); 
    Result := True; 
end; 

您還需要向AspectRatio屬性的屬性設置器添加代碼。因爲該財產的修改將需要引起控制權的重新調整。

+0

但現在我根本無法改變高度。 – ZigiZ

+0

您可以通過更改寬度。或者試試我最新的答案。您還需要在修改AspectRation時強制調整大小。 –