Come spostare e ridimensionare i controlli in fase di esecuzione (nelle applicazioni Delphi)

Ecco come abilitare il trascinamento e il ridimensionamento dei controlli (su un form Delphi) con un mouse, mentre l'applicazione è in esecuzione.

Form Editor in fase di esecuzione

Dopo aver posizionato un controllo (componente visivo) nel modulo, è possibile modificarne la posizione, le dimensioni e altre proprietà in fase di progettazione. Tuttavia, in alcune situazioni è necessario consentire a un utente dell'applicazione di riposizionare i controlli del modulo e modificarne le dimensioni in fase di esecuzione.

Per abilitare lo spostamento dell'utente in runtime e il ridimensionamento dei controlli su un modulo con un mouse, tre eventi relativi al mouse richiedono una gestione speciale: OnMouseDown, OnMouseMove e OnMouseUp.

In teoria, supponiamo che tu voglia consentire a un utente di spostare (e ridimensionare) un controllo pulsante, con un mouse, in fase di esecuzione. In primo luogo, gestisci l'evento OnMouseDown per consentire all'utente di "afferrare" il pulsante. Successivamente, l'evento OnMouseMove dovrebbe riposizionare (spostare, trascinare) il pulsante. Infine, OnMouseUp dovrebbe terminare l'operazione di spostamento.

Trascinamento e ridimensionamento dei controlli del modulo in pratica

Innanzitutto, rilascia diversi controlli su un modulo. Avere una casella di controllo per abilitare o disabilitare lo spostamento e il ridimensionamento dei controlli in fase di esecuzione.

Successivamente, definire tre procedure (nella sezione dell'interfaccia della dichiarazione del modulo) che gestiranno gli eventi del mouse come descritto sopra:

Digitare
TForm1 = classe(TForm) ...
procedura ControlMouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
procedura ControlMouseMove (Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedura ControlMouseUp (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
privato
inReposition: boolean; oldPos: TPoint;

Nota: sono necessarie due variabili a livello di modulo per contrassegnare se il movimento di controllo è in corso (inReposition) e per memorizzare la vecchia posizione di controllo (oldPos).

Nell'evento OnLoad del modulo, assegna le procedure di gestione degli eventi del mouse agli eventi corrispondenti (per quei controlli che desideri siano trascinabili / ridimensionabili):

procedura TForm1.FormCreate (Sender: TObject);
iniziare
Button1.OnMouseDown: = ControlMouseDown; Button1.OnMouseMove: = ControlMouseMove; Button1.OnMouseUp: = ControlMouseUp; Edit1.OnMouseDown: = ControlMouseDown; Edit1.OnMouseMove: = ControlMouseMove; Edit1.OnMouseUp: = ControlMouseUp; Panel1.OnMouseDown: = ControlMouseDown; Panel1.OnMouseMove: = ControlMouseMove; Panel1.OnMouseUp: = ControlMouseUp; Button2.OnMouseDown: = ControlMouseDown; Button2.OnMouseMove: = ControlMouseMove; Button2.OnMouseUp: = ControlMouseUp;
fine; (* FormCreate *)

Nota: il codice precedente consente il riposizionamento in fase di esecuzione di Button1, Edit1, Panel1 e Button2.

Infine, ecco il codice magico:

procedura TForm1.ControlMouseDown (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
iniziare
if (chkPositionRunTime.Checked) E
(Mittente is TWinControl) poi
iniziare
inReposition: = True; SetCapture (TWinControl (Sender) .Handle); GetCursorPos (oldPos);
fine;
fine; (* ControlMouseDown *)

ControlMouseDown in breve: una volta che un utente preme un pulsante del mouse su un controllo, se il riposizionamento in fase di esecuzione è abilitato (la casella di controllo chkPositionRunTime è selezionata) e il controllo che ha ricevuto il mouse premuto è anche derivato da TWinControl, segnare che il riposizionamento del controllo è in corso inReposition: = True) e assicurarsi che tutta l'elaborazione del mouse venga acquisita per il controllo, per impedire l'elaborazione degli eventi di "clic" predefiniti.

procedura TForm1.ControlMouseMove (Sender: TObject; Shift: TShiftState; X, Y: Integer);
const
minWidth = 20; minHeight = 20;
var
newPos: TPoint; frmPoint: TPoint;
iniziare
if inReposition poi
iniziare
  TWinControl (mittente) do
iniziare
GetCursorPos (newPos);
if ssShift in spostamento poi
iniziare // ridimensiona Screen.Cursor: = crSizeNWSE; frmPoint: = ScreenToClient (Mouse.CursorPos);
if frmPoint.X> minWidth poi
Larghezza: = frmPoint.X;
if frmPoint.Y> minHeight poi
Altezza: = frmPoint.Y;
fine
altro //mossa
iniziare
Screen.Cursor: = crSize; Sinistra: = Sinistra - oldPos.X + newPos.X; Top: = Top - oldPos.Y + newPos.Y; oldPos: = newPos;
fine;
fine;
fine;
fine; (* ControlMouseMove *)

ControlMouseMove in breve: cambia il cursore dello schermo per riflettere l'operazione: se il tasto Shift è premuto consenti il ​​ridimensionamento del controllo, o semplicemente sposta il controllo in una nuova posizione (dove sta andando il mouse). Nota: le costanti minWidth e minHeight forniscono una sorta di vincolo di dimensione (larghezza e altezza minime del controllo).

Quando il pulsante del mouse viene rilasciato, il trascinamento o il ridimensionamento è terminato:

procedura TForm1.ControlMouseUp (Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
iniziare
if inReposition poi
iniziare
Screen.Cursor: = crDefault; ReleaseCapture; inReposition: = False;
fine;
fine; (* ControlMouseUp *)

ControlMouseUp in breve: quando un utente ha finito di spostare (o ridimensionare il controllo) rilascia l'acquisizione del mouse (per abilitare l'elaborazione del clic predefinita) e contrassegna che il riposizionamento è finito.

E questo lo fa! Scarica l'applicazione di esempio e prova tu stesso.

Nota: un altro modo per spostare i controlli in fase di esecuzione è utilizzare le proprietà e i metodi relativi al trascinamento della selezione di Delphi (DragMode, OnDragDrop, DragOver, BeginDrag, ecc.). Il trascinamento e rilascio può essere utilizzato per consentire agli utenti di trascinare elementi da un controllo, ad esempio una casella di riepilogo o una visualizzazione ad albero, in un altro.

Come ricordare la posizione e le dimensioni del controllo?

Se consenti a un utente di spostare e ridimensionare i controlli del modulo, devi assicurarti che la posizione dei controlli venga in qualche modo salvata quando il modulo viene chiuso e che la posizione di ogni controllo venga ripristinata quando il modulo viene creato / caricato. Ecco come memorizzare le proprietà Left, Top, Width e Height, per ogni controllo su un form, in un file INI.

Che ne dici di 8 maniglie di dimensioni?

Quando si consente a un utente di spostare e ridimensionare i controlli nel modulo Delphi, in fase di esecuzione utilizzando il mouse, per imitare completamente l'ambiente in fase di progettazione, è necessario aggiungere otto quadratini di dimensione al controllo da ridimensionare.