De meest gebruikelijke manier om een venster te verplaatsen, is door het naar de titelbalk te slepen. Lees verder om erachter te komen hoe u sleepmogelijkheden kunt bieden Delphi-formulieren zonder titelbalk, zodat de gebruiker een formulier kan verplaatsen door ergens in het clientgebied te klikken.
Overweeg bijvoorbeeld het geval van een Windows-applicatie die geen titelbalk heeft, hoe kunnen we zo'n venster verplaatsen? In feite is het mogelijk om vensters te maken met een niet-standaard titelbalk en zelfs niet-rechthoekige vormen. Hoe kan Windows in dit geval weten waar de randen en de hoeken van het venster zijn?
Het WM_NCHitTest Windows-bericht
De Windows-besturingssysteem is sterk gebaseerd op berichten afhandelen. Wanneer u bijvoorbeeld op een venster of een besturingselement klikt, stuurt Windows het een wm_LButtonDown-bericht, met aanvullende informatie over waar de muiscursor zich bevindt en welke bedieningstoetsen zich momenteel bevinden ingedrukt. Klinkt bekend? Ja, dit is niets meer dan een OnMouseDown-evenement in Delphi.
Evenzo verzendt Windows een wm_NCHitTest-bericht wanneer een muisgebeurtenis treedt op, dat wil zeggen wanneer de cursor beweegt of wanneer een muisknop wordt ingedrukt of losgelaten.
Code voor invoer
Als we Windows kunnen laten denken dat de gebruiker de titelbalk sleept (heeft geklikt) in plaats van het clientgebied, dan kan de gebruiker het venster slepen door in het clientgebied te klikken. De eenvoudigste manier om dit te doen, is door Windows voor de gek te houden door te denken dat u daadwerkelijk op de titelbalk van een formulier klikt. Dit moet je doen:
1. Voeg de volgende regel toe aan de sectie "Privéaangiftes" van uw formulier (verklaring voor de behandeling van berichten):
procedure WMNCHitTest (var Msg: TWMNCHitTest); bericht WM_NCHitTest;
2. Voeg de volgende code toe aan het gedeelte "implementatie" van de eenheid van uw formulier (waarbij Form1 de veronderstelde formuliernaam is):
procedure TForm1.WMNCHitTest (var Msg: TWMNCHitTest);
beginnen
geërfd;
als Msg. Resultaat = htClient vervolgens Msg. Resultaat: = htCaption;
einde;
De eerste regel code in de berichtafhandelaar roept de overgeërfde methode aan om de standaardafhandeling voor het wm_NCHitTest-bericht te verkrijgen. Het If-gedeelte in de procedure onderschept en verandert het gedrag van uw venster. Dit is wat er werkelijk gebeurt: wanneer het besturingssysteem een wm_NCHitTest-bericht naar het venster stuurt, samen met de muiscoördinaten geeft het venster een code terug die aangeeft welk deel van zichzelf heeft geraakt. Het belangrijke stuk informatie, voor onze taak, zit in de waarde van de Msg. Resultaatveld. Op dit moment hebben we de mogelijkheid om het berichtresultaat te wijzigen.
Dit is wat we doen: als de gebruiker in het clientgebied van het formulier heeft geklikt, laten we Windows denken dat de gebruiker op de titelbalk heeft geklikt. In Object Pascal "woorden": als de waarde voor het retourneren van berichten HTCLIENT is, veranderen we deze eenvoudig in HTCAPTION.
Geen muisgebeurtenissen meer
Door het standaardgedrag van onze formulieren te wijzigen, verwijderen we de mogelijkheid van Windows om u te waarschuwen wanneer de muis zich boven het clientgebied bevindt. Een neveneffect van deze truc is dat uw formulier niet langer wordt gegenereerd gebeurtenissen voor muis berichten.
Venster zonder titel en zonder randen
Als u een venster zonder bijschrift zonder randen wilt dat lijkt op een zwevende werkbalk, stelt u het bijschrift van het formulier in op een lege tekenreeks, schakelt u alle BorderIcons uit en stelt u BorderStyle in op bsNone.
Een formulier kan op verschillende manieren worden gewijzigd door aangepaste code toe te passen in de CreateParams-methode.
Meer WM_NCHitTest-trucs
Als je het wm_NCHitTest-bericht nauwkeuriger bekijkt, zie je dat de geretourneerde waarde van de functie de positie van de cursorhotspot aangeeft. Hierdoor kunnen we wat meer spelen met de boodschap om vreemde resultaten te creëren.
Het volgende codefragment voorkomt dat gebruikers uw formulieren sluiten door op de knop Sluiten te klikken.
als Msg. Resultaat = htClose vervolgens Msg. Resultaat: = htNowhere;
Als de gebruiker het formulier probeert te verplaatsen door op de bijschriftbalk te klikken en te slepen, vervangt de code het resultaat van het bericht door een resultaat dat aangeeft dat de gebruiker op het clientgebied heeft geklikt. Dit voorkomt dat de gebruiker het venster met de muis beweegt (in tegenstelling tot wat we deden bij het bedelen van het artikel).
als Msg. Resultaat = htCaption vervolgens Msg. Resultaat: = htClient;
Componenten op een formulier hebben
In de meeste gevallen hebben we enkele componenten op een formulier. Laten we bijvoorbeeld zeggen dat één Panel-object op een formulier staat. Als de eigenschap Align van een paneel is ingesteld op alClient, vult het paneel het hele clientgebied zodat het onmogelijk is om het bovenliggende formulier te selecteren door erop te klikken. De bovenstaande code werkt niet - waarom? Dit komt omdat de muis altijd over het deelvenster Paneel beweegt, niet over het formulier.
Om ons formulier te verplaatsen door een paneel op het formulier te slepen, moeten we enkele regels code toevoegen in de OnMouseDown-gebeurtenisprocedure voor het paneelonderdeel:
procedure TForm1.Panel1MouseDown
(Afzender: TObject; Knop: TMouseButton;
Shift: TShiftState; X, Y: geheel getal);
beginnen
ReleaseCapture;
SendMessage (Form1.Handle, WM_SYSCOMMAND, 61458, 0);
einde;
Notitie: Deze code werkt niet met niet-vensterbesturingselementen zoals TLabel-componenten.