Dra ett Delphi-formulär utan bildtexten

Det vanligaste sättet att flytta ett fönster är att dra det i titelraden. Läs vidare för att ta reda på hur du kan tillhandahålla dragfunktioner för Delphi-formulär utan titelraden, så att användaren kan flytta ett formulär genom att klicka var som helst i klientområdet.

Tänk till exempel på fallet med ett Windows-program som inte har en titelrad, hur kan vi flytta ett sådant fönster? Det är faktiskt möjligt att skapa fönster med en icke-standardiserad titelrad och till och med icke-rektangulära former. I det här fallet, hur kan Windows veta var gränserna och hörnen på fönstret är?

WM_NCHitTest Windows-meddelandet

Windows-operativsystemet är starkt baserat på hantering av meddelanden. När du till exempel klickar på ett fönster eller en kontroll skickar Windows det ett wm_LButtonDown-meddelande, med ytterligare information om var muspekaren befinner sig och vilka kontrolltangenter som för närvarande trycks ned. Låter bekant? Ja, det här är inget annat än ett OnMouseDown-evenemang i Delphi.

På samma sätt skickar Windows ett wm_NCHitTest-meddelande när en mushändelse inträffar, det vill säga när markören rör sig, eller när en musknapp trycks ned eller släpps.

Kod att mata in

Om vi ​​kan få Windows att tro att användaren drar (har klickat på) titelraden snarare än klientområdet, kan användaren dra fönstret genom att klicka i klientområdet. Det enklaste sättet att göra detta är att "lura" Windows att tro att du faktiskt klickar på rubriken på ett formulär. Här är vad du måste göra:

1. Sätt in följande rad i avsnittet "Privata deklarationer" i formuläret (förklaring om hantering av meddelanden):

 procedur WMNCHitTest (var Msg: TWMNCHitTest); meddelande WM_NCHitTest; 

2. Lägg till följande kod i avsnittet "implementering" i din formulärsenhet (där Form1 är det antagna formulärnamnet):

 procedur TForm1.WMNCHitTest (var Msg: TWMNCHitTest);

Börja

    ärvt;

  
om Msg.Result = htClient sedan Msg.Result: = htCaption;

slutet; 

Den första raden i koden i meddelandeshanteraren kallar den ärvda metoden för att få standardhanteringen för meddelandet wm_NCHitTest. If-delen i proceduren fångar upp och ändrar ditt fönsterbeteende. Det här är vad som faktiskt händer: när operativsystemet skickar ett wm_NCHitTest-meddelande till fönstret, tillsammans med muskoordinaterna, returnerar fönstret en kod som anger vilken del av sig själv som har drabbats. Den viktiga informationen för vår uppgift ligger i värdet av Msg.Result-fältet. Just nu har vi en möjlighet att ändra meddelanderesultatet.

Det här gör vi: Om användaren har klickat i formulärets klientområde gör vi Windows för att tro att användaren klickade på titelfältet. I Objekt Pascal "ord": om meddelandets returvärde är HTCLIENT, ändrar vi helt enkelt det till HTCAPTION.

Inga fler mushändelser

Genom att ändra standardbeteendet för våra formulär tar vi bort Windows möjlighet att meddela dig när musen är över klientområdet. En biverkning av detta trick är att din form inte längre genererar händelser för musmeddelanden.

Fönster med bildtexter utan gränser

Om du vill ha ett bildtextsfritt gränslöst fönster som liknar ett flytande verktygsfält, ställ in Formulärens bildtext till en tom sträng, inaktivera alla BorderIcons och ställ BorderStyle till bsNone.

Ett formulär kan ändras på olika sätt genom att använda anpassad kod i metoden CreateParams.

Fler WM_NCHitTest-trick

Om du tittar mer noggrant på wm_NCHitTest-meddelandet ser du att funktionens returvärde indikerar positionen för markörens heta punkt. Detta gör att vi kan spela lite mer med meddelandet för att skapa konstiga resultat.

Följande kodfragment förhindrar användare att stänga dina formulär genom att klicka på knappen Stäng.

 om Msg.Result = htClose sedan Msg.Result: = htNowhere; 

Om användaren försöker flytta formuläret genom att klicka på bildtexten och dra, ersätter koden resultatet av meddelandet med ett resultat som indikerar att användaren klickade på klientområdet. Detta förhindrar användaren från att flytta fönstret med musen (mittemot vad vi gjorde i artikelns tiggeri).

 om Msg.Result = htCaption sedan Msg.Result: = htClient; 

Att ha komponenter på ett formulär

I de flesta fall har vi några komponenter på ett formulär. Låt oss till exempel säga att ett panelobjekt finns på ett formulär. Om egenskapen Justera för en panel är inställd på alClient fyller panelen hela klientområdet så att det är omöjligt att välja överordnad form genom att klicka på den. Koden ovan fungerar inte - varför? Det beror på att musen alltid rör sig över panelen, inte formen.

För att flytta vårt formulär genom att dra en panel på formuläret måste vi lägga till några rader med kod i händelseproceduren OnMouseDown för panelen:

 procedur TForm1.Panel1MouseDown

   (Avsändare: TObject; Knapp: TMouseButton;
   Skift: TShiftState; X, Y: heltal);
Börja

    ReleaseCapture;

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

 slutet; 

Notera: Den här koden fungerar inte med kontroller utan fönster som TLabel-komponenter.