Ziehen Sie ein Delphi-Formular ohne die Beschriftungsleiste

Die häufigste Methode zum Verschieben eines Fensters besteht darin, es an der Titelleiste zu ziehen. Lesen Sie weiter, um herauszufinden, wie Sie das Ziehen von Delphi-Formularen ohne Titelleiste ermöglichen können, damit der Benutzer ein Formular verschieben kann, indem er auf eine beliebige Stelle im Clientbereich klickt.

Angenommen, Sie haben eine Windows-Anwendung ohne Titelleiste. Wie können Sie ein solches Fenster verschieben? Tatsächlich ist es möglich, Fenster mit einer nicht standardmäßigen Titelleiste und sogar nicht rechteckigen Formen zu erstellen. Woher sollte Windows in diesem Fall wissen, wo sich die Ränder und Ecken des Fensters befinden??

Die WM_NCHitTest Windows Nachricht

Das Windows-Betriebssystem basiert stark auf der Verarbeitung von Nachrichten. Wenn Sie beispielsweise auf ein Fenster oder ein Steuerelement klicken, sendet Windows eine wm_LButtonDown-Nachricht mit zusätzlichen Informationen darüber, wo sich der Mauszeiger befindet und welche Steuertasten gerade gedrückt werden. Klingt vertraut? Ja, dies ist nichts anderes als ein OnMouseDown-Ereignis in Delphi.

Ebenso sendet Windows eine wm_NCHitTest-Nachricht, wenn ein Mausereignis eintritt, dh wenn sich der Cursor bewegt oder wenn eine Maustaste gedrückt oder losgelassen wird.

Code zur Eingabe

Wenn wir Windows glauben lassen können, dass der Benutzer die Titelleiste und nicht den Client-Bereich zieht (darauf geklickt hat), könnte der Benutzer das Fenster ziehen, indem er in den Client-Bereich klickt. Der einfachste Weg, dies zu tun, besteht darin, Windows zu "täuschen", dass Sie tatsächlich auf die Titelleiste eines Formulars klicken. Folgendes müssen Sie tun:

1. Fügen Sie die folgende Zeile in den Abschnitt "Private Deklarationen" Ihres Formulars ein (Deklaration des Nachrichtenbehandlungsverfahrens):

 Verfahren WMNCHitTest (var Msg: TWMNCHitTest); Botschaft WM_NCHitTest; 

2. Fügen Sie den folgenden Code in den Abschnitt "Implementierung" der Formulareinheit ein (wobei Form1 der angenommene Formularname ist):

 Verfahren TForm1.WMNCHitTest (var Msg: TWMNCHitTest);

Start

    vererbt;

  
wenn Msg.Result = htClient dann Msg.Result: = htCaption;

Ende; 

Die erste Codezeile in der Nachrichtenbehandlungsroutine ruft die geerbte Methode auf, um die Standardbehandlung für die Nachricht wm_NCHitTest abzurufen. Der If-Teil der Prozedur fängt das Verhalten Ihres Fensters ab und ändert es. Folgendes passiert tatsächlich: Wenn das Betriebssystem eine wm_NCHitTest-Nachricht zusammen mit den Mauskoordinaten an das Fenster sendet, gibt das Fenster einen Code zurück, der angibt, welcher Teil von sich selbst getroffen wurde. Die wichtige Information für unsere Aufgabe ist der Wert des Feldes Msg.Result. An dieser Stelle haben wir die Möglichkeit, das Nachrichtenergebnis zu ändern.

Folgendes tun wir: Wenn der Benutzer auf den Clientbereich des Formulars geklickt hat, lässt Windows den Benutzer auf die Titelleiste klicken. In Object Pascal "words": Wenn der Rückgabewert der Nachricht HTCLIENT ist, ändern wir ihn einfach in HTCAPTION.

Keine Mausereignisse mehr

Durch Ändern des Standardverhaltens unserer Formulare wird die Möglichkeit von Windows entfernt, Sie zu benachrichtigen, wenn sich der Mauszeiger über dem Clientbereich befindet. Ein Nebeneffekt dieses Tricks ist, dass Ihr Formular keine Ereignisse mehr für Mausnachrichten generiert.

Captionless-Borderless-Fenster

Wenn Sie ein beschriftungsloses, randloses Fenster möchten, das einer schwebenden Symbolleiste ähnelt, setzen Sie die Beschriftung des Formulars auf eine leere Zeichenfolge, deaktivieren Sie alle BorderIcons und setzen Sie den BorderStyle auf bsNone.

Ein Formular kann auf verschiedene Arten geändert werden, indem in der CreateParams-Methode benutzerdefinierter Code angewendet wird.

Weitere WM_NCHitTest-Tricks

Wenn Sie sich die Nachricht wm_NCHitTest genauer ansehen, werden Sie feststellen, dass der Rückgabewert der Funktion die Position des Cursor-Hotspots angibt. Dies ermöglicht es uns, mit der Nachricht ein wenig mehr zu spielen, um seltsame Ergebnisse zu erzielen.

Das folgende Codefragment verhindert, dass Benutzer Ihre Formulare durch Klicken auf die Schaltfläche Schließen schließen können.

 wenn Msg.Result = htClose dann Msg.Result: = htNowhere; 

Wenn der Benutzer versucht, das Formular durch Klicken auf die Beschriftungsleiste und Ziehen zu verschieben, ersetzt der Code das Ergebnis der Nachricht durch ein Ergebnis, das angibt, dass der Benutzer auf den Clientbereich geklickt hat. Dies verhindert, dass der Benutzer das Fenster mit der Maus bewegt (im Gegensatz zu dem, was wir beim Aufrufen des Artikels getan haben)..

 wenn Msg.Result = htCaption dann Msg.Result: = htClient; 

Komponenten in einem Formular haben

In den meisten Fällen befinden sich einige Komponenten in einem Formular. Angenommen, ein Panel-Objekt befindet sich in einem Formular. Wenn die Align-Eigenschaft eines Panels auf alClient festgelegt ist, füllt das Panel den gesamten Clientbereich aus, sodass das übergeordnete Formular nicht durch Klicken ausgewählt werden kann. Der obige Code funktioniert nicht - warum? Dies liegt daran, dass sich die Maus immer über die Panel-Komponente und nicht über das Formular bewegt.

Um unser Formular durch Ziehen eines Bedienfelds auf dem Formular zu verschieben, müssen Sie einige Codezeilen in die OnMouseDown-Ereignisprozedur für die Panel-Komponente einfügen:

 Verfahren TForm1.Panel1MouseDown

   (Absender: TObject; Schaltfläche: TMouseButton;
   Shift: TShiftState; X, Y: Ganzzahl);
Start

    ReleaseCapture;

    SendMessage (Form1.Handle, WM_SYSCOMMAND, 61458, 0);

 Ende; 

Hinweis: Dieser Code funktioniert nicht mit Nicht-Fenster-Steuerelementen wie TLabel-Komponenten.