Home | Chi sono | Contattami
 

Progr. lineare

Delphi
 
Componenti
  Database
 
Miei articoli

Windows

Miei articoli 

 

Come ridimensionare ricorsivamente tutti i controlli in una form quando questa viene ridimensionata


Quello che vado a presentare è uno dei primi componenti Delphi che ho creato: in soldoni, una volta messo su una Form, consente il ridemensionamento automatico e ricorsivo di tutti i controlli messi sulla Form.

1. Passo dopo passo

La chiave di tutto è l' implementazione dell' evento OnResize della classe TForm che si verifica ogni volta che la Form viene ridimensionata. Tutte le volte che la TForm viene ridimensionata si passa da una altezza iniziale PH ad una altezza finale HH e da una ampiezza iniziale PW ad una ampiezza finale WW.

All' inizio (ad esempio nell' evento OnCreate della TForm) registriamo i valori di PW e PH:

Form1.FormCreate(Sender: TObject); begin { ... } PW := Form1.ClientWidth; PH := Form1.ClientHeight; { ... } end;

Poi implementiamo l' evento OnResize nel seguente modo:

Form1.FormResize(Sender: TObject); begin WW := Form1.ClientWidth; {nuovo valore dell' ampiezza dopo il ridimensionamento} HH := Form1.ClientHeight; {nuovo valore dell' altezza dopo il ridimensionamento} {qui inseriremo il codire di ridimensionamento ricorsivo dei controlli} {dimensioni attuali: saranno le vecchie dimensioni nel corso del prossimo ridimensionamento} PW := WW; PH := HH; end;

Analizziamo ora il codice di ridimensionamento ricorsivo. (che andremo ad inserire all' interno dell' implementazione dell' evento OnResize della TForm:

{ ... } for I := 0 to (Form1.ControlCount - 1) do begin ChangeDims(Form1.Controls[i], WW, PW, HH, PH); end;

ChangeDims è la procedura che ridimensiona (con ricorsione) i controlli figli.

procedure ChangeDims(Control:TControl; WW, PW, HH, PH: Integer); var L, T, W, H: integer; begin if Control is TWinControl then (Control as TWinControl).DisableAlign; try if Control is TWinControl then ScaleCtrls(Control as TWinControl, WW, PW, HH, PH); L := MulDiv(Control.Left, WW, PW); T := MulDiv(Control.Top, HH, PH); W := MulDiv(Control.Left + Control.Width, WW, PW) - L; H := MulDiv(Control.Top + Control.Height, HH, PH) - T; Control.SetBounds(L, T, W, H); finally if Control is TWinControl then (Control as TWinControl).DisableAlign; end; end; procedure ScaleCtrls(Control: TWinControl; WW, PW, HH, PH: Integer); var I: Integer; begin for I := 0 to Control.ControlCount - 1 do ChangeDims(Control.Controls[i], WW, PW, HH, PH); end;

Inserendo il codice soprastante si ottiene il ridimensionamento automatico di tutti i controlli figli (ricorsivamente su tutti i controlli figli dei figli) al ridimensionarsi della Form. A questo punto passiamo ad incapsulare questa funzioalità in un componente in quanto non voglio assolutamente riempire di codice tutte le volte l' implementazione delle mie Form: voglio semplicemente sbattere un componente sulla Form e basta. Questo componente non fa altro che assegnare l' implementazione dell' evento OnResize della Form dopo aver assegnato l' implementazione eventualmente già presente dello stesso evento. Di conseguenza l' evento OnResize della Form consisterà nella chiamata all' implemetazione (eventualmente presente) definita dall' utente, seguita dall' implementazione sopra citata che è appunto responsabile del ridimensionamento ricorsivo. In questo modo chiunque usi il componente, può in ogni caso continuare ad usare l' evento OnResize senza che questo venga coperto dall' implementazione fornita dal componente
 

2. Componente

Eccoci giunti finalmente alla stesura del codice del componente

unit Resize; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TResize = class(TComponent) private { Private declarations } FForm1: TForm; PW, PH: integer; FOnResizeEvent: TNotifyEvent; procedure ScaleCtrls(Control:TWinControl; WW, PW, HH, PH: Integer); procedure ChangeDims(Control:TControl; WW, PW, HH, PH: Integer); procedure OnResizeEvent(Sender: TObject); procedure Resize(); protected { Protected declarations } public { Public declarations } constructor Create(AOwner: TComponent); override; destructor Destroy(); override; published { Published declarations } end; procedure Register; implementation constructor TResize.Create(AOwner: TComponent); begin inherited Create(AOwner); if csDesigning in ComponentState then Exit; FForm1 := (Owner as TForm); PW := FForm1.ClientWidth; PH := FForm1.ClientHeight; if Assigned(FForm1.OnResize) then begin FOnResizeEvent := FForm1.OnResize; end; FForm1.OnResize := OnResizeEvent; end; destructor TResize.Destroy(); begin if not (csDesigning in ComponentState) then FForm1.OnResize := FOnResizeEvent; inherited Destroy(); end; procedure TResize.ScaleCtrls(Control: TWinControl; WW, PW, HH, PH: Integer); var I: Integer; begin for I := 0 to Control.ControlCount - 1 do ChangeDims(Control.Controls[i], WW, PW, HH, PH); end; procedure TResize.ChangeDims(Control:TControl; WW, PW, HH, PH: Integer); var L, T, W, H: integer; begin if Control is TWinControl then (Control as TWinControl).DisableAlign; try if Control is TWinControl then ScaleCtrls(Control as TWinControl, WW, PW, HH, PH); L := MulDiv(Control.Left, WW, PW); T := MulDiv(Control.Top, HH, PH); W := MulDiv(Control.Left + Control.Width, WW, PW) - L; H := MulDiv(Control.Top + Control.Height, HH, PH) - T; Control.SetBounds(L, T, W, H); finally if Control is TWinControl then (Control as TWinControl).DisableAlign; end; end; procedure TResize.OnResizeEvent(Sender: TObject); begin if Assigned(FOnResizeEvent) then begin FOnResizeEvent(Sender); end; Resize(); end; procedure TResize.Resize(); var L, T, R, B, W, H, WW, HH, I : Integer; begin WW := FForm1.ClientWidth; HH := FForm1.ClientHeight; for I := 0 to (FForm1.ControlCount - 1) do begin ChangeDims(FForm1.Controls[i], WW, PW, HH, PH); end; PW := WW; PH := HH; end; procedure Register; begin RegisterComponents('Carlo Pasolini', [TResize]); end; end.

 

 

 


 

 
 
Your Ad Here