Den vanligste måten å flytte et vindu på er å dra det ved tittellinjen. Les videre for å finne ut hvordan du kan tilby drafunksjoner for Delphi skjemaer uten tittellinje, slik at brukeren kan flytte et skjema ved å klikke hvor som helst på klientområdet.
Vurder for eksempel saken om a Windows-applikasjon som ikke har tittellinje, hvordan kan vi flytte et slikt vindu? Det er faktisk mulig å lage vinduer med en ikke-standard tittellinje og til og med ikke-rektangulære former. I dette tilfellet, hvordan kunne Windows vite hvor grensene og hjørnene av vinduet er?
WM_NCHitTest Windows-melding
De Windows-operativsystem er sterkt basert på håndtering av meldinger. Når du for eksempel klikker på et vindu eller en kontroll, sender Windows det en wm_LButtonDown-melding, med tilleggsinformasjon om hvor musepekeren er og hvilke kontrolltaster som er for øyeblikket trykket. Høres kjent ut? Ja, dette er ikke noe mer enn et OnMouseDown-arrangement i Delphi.
Tilsvarende sender Windows en wm_NCHitTest-melding når en
musebegivenhet oppstår, det vil si når markøren beveger seg, eller når en museknapp trykkes eller slippes.Kode som skal legges inn
Hvis vi kan få Windows til å tenke at brukeren drar (har klikket på) tittellinjen i stedet for klientområdet, kan brukeren dra vinduet ved å klikke i klientområdet. Den enkleste måten å gjøre dette på er å "lure" Windows til å tro at du faktisk klikker på tittellinjen til et skjema. Her er hva du må gjøre:
1. Sett inn følgende linje i skjemaets "Private erklæringer" (meldingshåndteringsprosedyreerklæring):
fremgangsmåte WMNCHitTest (Var Msg: TWMNCHitTest); beskjed WM_NCHitTest;
2. Legg til følgende kode i "implementering" -delen av skjemaets enhet (der Form1 er det antatte skjemanavnet):
fremgangsmåte TForm1.WMNCHitTest (Var Msg: TWMNCHitTest);
begynne
arvet;
hvis Msg. Resultat = htClient deretter Msg. Resultat: = htCaption;
slutt;
Den første kodelinjen i meldingsbehandleren kaller den arvelige metoden for å få standardhåndtering for wm_NCHitTest-meldingen. Hvis-delen i prosedyren avskjærer og endrer vinduets oppførsel. Dette er hva som faktisk skjer: når operativsystemet sender en wm_NCHitTest-melding til vinduet, sammen med musekoordinatene returnerer vinduet en kode som sier hvilken del av seg selv som har blitt truffet. Den viktige informasjonen, for oppgaven vår, er verdien av Msg. Resultatfelt. På dette tidspunktet har vi en mulighet til å endre meldingsresultatet.
Dette gjør vi: Hvis brukeren har klikket i skjemaets klientområde, gjør vi Windows til å tro at brukeren klikket på tittellinjen. I Objekt Pascal "ord": Hvis verdien for meldingen er HTCLIENT, endrer vi den til HTCAPTION.
Ingen flere museventer
Ved å endre standardoppførselen til skjemaene fjerner vi muligheten til at Windows kan varsle deg når musen er over klientområdet. En bivirkning av dette trikset er at skjemaet ditt ikke lenger vil generere hendelser for mus meldinger.
Bildetekstfritt-uten vindu
Hvis du vil ha et bildetekstfritt grenseløst vindu som ligner på en flytende verktøylinje, setter du Forms Caption til en tom streng, deaktiverer alle BorderIcons og setter BorderStyle til bsNone.
Et skjema kan endres på forskjellige måter ved å bruke tilpasset kode i CreateParams-metoden.
Flere WM_NCHitTest-triks
Hvis du ser mer nøye på wm_NCHitTest-meldingen, vil du se at returverdien for funksjonen indikerer plasseringen av markørens hete sted. Dette gjør at vi kan spille litt mer med meldingen for å skape rare resultater.
Følgende kodefragment forhindrer brukere i å lukke skjemaene dine ved å klikke på Lukk-knappen.
hvis Msg. Resultat = htLukk deretter Msg. Resultat: = htNowhere;
Hvis brukeren prøver å flytte skjemaet ved å klikke på bildetekstlinjen og dra, erstatter koden resultatet av meldingen med et resultat som indikerer at brukeren har klikket på klientområdet. Dette forhindrer brukeren i å bevege vinduet med musen (motsatt av det vi gjorde i tigging av artikkelen).
hvis Msg. Resultat = htCaption deretter Msg. Resultat: = htClient;
Å ha komponenter på et skjema
I de fleste tilfeller har vi noen komponenter på et skjema. La oss for eksempel si at ett panelobjekt er på et skjema. Hvis Align-egenskapen til et panel er satt til alClient, fyller panelet hele klientområdet slik at det er umulig å velge overordnet skjema ved å klikke på det. Koden over fungerer ikke - hvorfor? Det er fordi musen alltid beveger seg over panelkomponenten, ikke skjemaet.
For å flytte skjemaet vårt ved å dra et panel på skjemaet, må vi legge til noen par linjer med kode i OnMouseDown hendelsesprosedyre for panelkomponenten:
fremgangsmåte TForm1.Panel1MouseDown
(Avsender: TObject; Knapp: TMouseButton;
Skift: TShiftState; X, Y: Heltall);
begynne
ReleaseCapture;
SendMessage (Form1.Handle, WM_SYSCOMMAND, 61458, 0);
slutt;
Merk: Denne koden fungerer ikke med ikke-vinduskontroller som TLabel-komponenter.