Il modo più comune per spostare una finestra è trascinarla dalla sua barra del titolo. Continua a leggere per scoprire come è possibile fornire funzionalità di trascinamento per Delphi moduli senza barra del titolo, quindi l'utente può spostare un modulo facendo clic in un punto qualsiasi dell'area client.
Ad esempio, considera il caso di a Applicazione Windows che non ha una barra del titolo, come possiamo spostare una finestra del genere? In effetti, è possibile creare finestre con una barra del titolo non standard e persino forme non rettangolari. In questo caso, come può Windows sapere dove sono i bordi e gli angoli della finestra?
Il messaggio Windows WM_NCHitTest
Il Sistema operativo Windows è fortemente basato su gestione dei messaggi. Ad esempio, quando fai clic su una finestra o un controllo, Windows gli invia un messaggio wm_LButtonDown, con ulteriori informazioni su dove si trova il cursore del mouse e quali tasti di controllo sono attualmente premuto. Suona familiare? Sì, questo non è altro che un evento OnMouseDown a Delfi.
Allo stesso modo, Windows invia un messaggio wm_NCHitTest ogni volta che a evento del mouse si verifica, ovvero quando si sposta il cursore o quando si preme o rilascia un pulsante del mouse.
Codice da inserire
Se riusciamo a far pensare a Windows che l'utente sta trascinando (facendo clic su) la barra del titolo anziché l'area client, l'utente può trascinare la finestra facendo clic nell'area client. Il modo più semplice per farlo è "ingannare" Windows nel pensare che stai effettivamente facendo clic sulla barra del titolo di un modulo. Ecco cosa devi fare:
1. Inserire la seguente riga nella sezione "Dichiarazioni private" del modulo (dichiarazione della procedura di gestione dei messaggi):
procedura WMNCHitTest (var Messaggio: TWMNCHitTest); Messaggio WM_NCHITTEST;
2. Aggiungi il seguente codice nella sezione "implementazione" dell'unità del modulo (dove Form1 è il nome del modulo assunto):
procedura TForm1.WMNCHitTest (var Messaggio: TWMNCHitTest);
inizio
ereditato;
Se Msg. Risultato = htClient poi Msg. Risultato: = htCaption;
fine;
La prima riga di codice nel gestore messaggi chiama il metodo ereditato per ottenere la gestione predefinita per il messaggio wm_NCHitTest. La parte If della procedura intercetta e modifica il comportamento della finestra. Questo è ciò che realmente accade: quando il sistema operativo invia un messaggio wm_NCHitTest alla finestra, insieme alle coordinate del mouse, la finestra restituisce un codice che indica quale parte di sé ha stato colpito. L'importante informazione, per il nostro compito, è nel valore del messaggio. Campo risultato. A questo punto, abbiamo l'opportunità di modificare il risultato del messaggio.
Questo è ciò che facciamo: se l'utente ha fatto clic nell'area client del modulo, facciamo in modo che Windows pensi che l'utente abbia fatto clic sulla barra del titolo. Nel Oggetto Pascal "parole": se il valore di ritorno del messaggio è HTCLIENT, lo cambiamo semplicemente in HTCAPTION.
Nessun altro evento del mouse
Modificando il comportamento predefinito dei nostri moduli, rimuoviamo la capacità di Windows di avvisare l'utente quando il mouse si trova nell'area client. Un effetto collaterale di questo trucco è che il modulo non genererà più eventi per il mouse messaggi.
Finestra senza didascalia-senza bordi
Se si desidera una finestra senza bordi senza didascalia simile a una barra degli strumenti mobile, impostare la didascalia del modulo su una stringa vuota, disabilitare tutti gli BorderIcons e impostare BorderStyle su bsNone.
Un modulo può essere modificato in vari modi applicando il codice personalizzato nel metodo CreateParams.
Altri trucchi WM_NCHitTest
Se osservi più attentamente il messaggio wm_NCHitTest vedrai che il valore di ritorno della funzione indica la posizione del punto attivo del cursore. Questo ci consente di giocare un po 'di più con il messaggio per creare risultati strani.
Il seguente frammento di codice impedirà agli utenti di chiudere i moduli facendo clic sul pulsante Chiudi.
Se Msg. Risultato = htChiudi poi Msg. Risultato: = htNowhere;
Se l'utente sta tentando di spostare il modulo facendo clic sulla barra dei sottotitoli e trascinandolo, il codice sostituisce il risultato del messaggio con un risultato che indica che l'utente ha fatto clic nell'area client. Questo impedisce all'utente di spostare la finestra con il mouse (al contrario di quello che stavamo facendo nell'accattonaggio dell'articolo).
Se Msg. Risultato = htCaption poi Msg. Risultato: = htClient;
Avere componenti in un modulo
Nella maggior parte dei casi, avremo alcuni componenti in un modulo. Diciamo, ad esempio, che un oggetto Panel si trova su un modulo. Se la proprietà Allinea di un pannello è impostata su alClient, il Pannello riempie l'intera area client in modo che sia impossibile selezionare il modulo padre facendo clic su di esso. Il codice sopra non funzionerà - perché? È perché il mouse si sposta sempre sul componente Pannello, non sul modulo.
Per spostare il nostro modulo trascinando un pannello sul modulo, dobbiamo aggiungere alcune righe di codice nella procedura dell'evento OnMouseDown per il componente Pannello:
procedura TForm1.Panel1MouseDown
(Mittente: TObject; Pulsante: TMouseButton;
Maiusc: TShiftState; X, Y: intero);
inizio
ReleaseCapture;
SendMessage (Form1.Handle, WM_SYSCOMMAND, 61458, 0);
fine;
Nota: Questo codice non funziona con i controlli non di finestra come Componenti TLabel.