Ο πιο συνηθισμένος τρόπος για να μετακινήσετε ένα παράθυρο είναι να τον σύρετε από τη γραμμή τίτλου του. Διαβάστε παρακάτω για να μάθετε πώς μπορείτε να παρέχετε δυνατότητες μεταφοράς Delphi μορφές χωρίς γραμμή τίτλου, οπότε ο χρήστης μπορεί να μετακινήσει μια φόρμα κάνοντας κλικ οπουδήποτε στην περιοχή του πελάτη.
Για παράδειγμα, εξετάστε την περίπτωση α Εφαρμογή Windows που δεν έχει γραμμή τίτλου, πώς μπορούμε να μεταφέρουμε ένα τέτοιο παράθυρο; Στην πραγματικότητα, είναι δυνατό να δημιουργηθούν παράθυρα με μια μη τυπική γραμμή τίτλου και ακόμη και μη ορθογώνια έντυπα. Σε αυτήν την περίπτωση, πώς θα μπορούσαν τα Windows να γνωρίζουν πού είναι τα σύνορα και οι γωνίες του παραθύρου;
Το μήνυμα WM_NCHitTest των Windows
ο Λειτουργικό σύστημα Windows βασίζεται σε μεγάλο βαθμό χειρισμού μηνυμάτων. Για παράδειγμα, όταν κάνετε κλικ σε ένα παράθυρο ή σε ένα στοιχείο ελέγχου, τα Windows στέλνουν ένα μήνυμα wm_LButtonDown, με πρόσθετες πληροφορίες σχετικά με το πού είναι ο δρομέας του ποντικιού και ποια πλήκτρα ελέγχου είναι αυτή τη στιγμή πατημένο. Ακούγεται γνωστό? Ναι, αυτό δεν είναι τίποτα περισσότερο από ένα γεγονός OnMouseDown στους Δελφούς.
Ομοίως, τα Windows στέλνουν ένα μήνυμα wm_NCHitTest όποτε a ποντικιού συμβαίνει, δηλαδή όταν ο κέρσορας μετακινείται ή όταν πιέζεται ή απελευθερώνεται ένα κουμπί του ποντικιού.
Κωδικοποίηση εισόδου
Εάν μπορούμε να κάνουμε τα Windows να πιστεύουν ότι ο χρήστης σέρνει (κάντε κλικ) στην γραμμή τίτλου και όχι στην περιοχή του πελάτη, τότε ο χρήστης μπορεί να σύρει το παράθυρο κάνοντας κλικ στην περιοχή του πελάτη. Ο ευκολότερος τρόπος για να γίνει αυτό είναι να "ξεγελάσουν" τα Windows για να σκεφτούν ότι κάνετε κλικ στην μπάρα τίτλου μιας φόρμας. Εδώ πρέπει να κάνετε:
1. Καταχωρίστε την ακόλουθη γραμμή στην ενότητα "Ιδιωτικές δηλώσεις" της φόρμας (δήλωση διαδικασίας χειρισμού μηνυμάτων):
διαδικασία WMNCHitTest (var Msg: TWMNCHitTest); μήνυμα WM_NCHitTest;
2. Προσθέστε τον ακόλουθο κώδικα στην ενότητα "εφαρμογή" της μονάδας της φόρμας σας (όπου το Form1 είναι το όνομα της φόρμας):
διαδικασία TForm1.WMNCHitTest (var Msg: TWMNCHitTest);
ξεκινήσει
κληρονόμησε;
αν Msg. Αποτέλεσμα = htClient έπειτα Msg. Αποτέλεσμα: = htCaption;
τέλος;
Η πρώτη γραμμή κώδικα του χειριστή μηνυμάτων καλεί τη μέθοδο κληρονομούμενης μεθόδου για να αποκτήσει τον προεπιλεγμένο χειρισμό για το μήνυμα wm_NCHitTest. Το τμήμα If στη διαδικασία παρακολουθεί και αλλάζει τη συμπεριφορά του παραθύρου σας. Αυτό συμβαίνει στην πραγματικότητα: όταν το λειτουργικό σύστημα στέλνει ένα μήνυμα wm_NCHitTest στο παράθυρο, μαζί με τις συντεταγμένες του ποντικιού, το παράθυρο επιστρέφει έναν κώδικα που δηλώνει ποιο τμήμα του έχει χτύπησε. Το σημαντικό κομμάτι των πληροφοριών, για το καθήκον μας, είναι στην αξία του Msg. Πεδίο αποτελέσματος. Σε αυτό το σημείο, έχουμε την ευκαιρία να τροποποιήσουμε το αποτέλεσμα του μηνύματος.
Αυτό κάνουμε: αν ο χρήστης έχει κάνει κλικ στην περιοχή πελάτη της φόρμας, κάνουμε τα Windows να σκέφτονται ότι ο χρήστης έκανε κλικ στη γραμμή τίτλου. Σε Αντικείμενο Pascal "λέξεις": αν η τιμή επιστροφής μηνύματος είναι HTCLIENT, απλά την αλλάζουμε στο HTCAPTION.
Δεν υπάρχουν περισσότερα συμβάντα στο ποντίκι
Αλλάζοντας την προεπιλεγμένη συμπεριφορά των εντύπων μας, καταργούμε την ικανότητα των Windows να σας ειδοποιούν όταν το ποντίκι είναι πάνω από την περιοχή του πελάτη. Μια παρενέργεια από αυτό το κόλπο είναι ότι η φόρμα σας δεν θα παράγει πλέον εκδηλώσεις για το ποντίκι μηνυμάτων.
Παράθυρο χωρίς περίγραμμα χωρίς περιορισμούς
Εάν θέλετε ένα παράθυρο χωρίς περιγράμματα χωρίς χαρακτήρες παρόμοιο με μια κυμαινόμενη γραμμή εργαλείων, ορίστε τη λεζάντα της φόρμας σε μια κενή συμβολοσειρά, απενεργοποιήστε όλες τις γραμμές BorderIcons και ρυθμίστε το BorderStyle στο bsNone.
Μια φόρμα μπορεί να αλλάξει με διάφορους τρόπους εφαρμόζοντας προσαρμοσμένο κώδικα στη μέθοδο CreateParams.
Περισσότερα κόλπα WM_NCHitTest
Εάν κοιτάξετε προσεκτικότερα το μήνυμα wm_NCHitTest, θα δείτε ότι η επιστρεφόμενη τιμή της λειτουργίας υποδεικνύει τη θέση του hot spot του δρομέα. Αυτό μας δίνει τη δυνατότητα να παίξουμε λίγο περισσότερο με το μήνυμα για να δημιουργήσουμε παράξενα αποτελέσματα.
Το παρακάτω κομμάτι κώδικα θα εμποδίσει τους χρήστες να κλείσουν τις φόρμες κάνοντας κλικ στο κουμπί Κλείσιμο.
αν Msg. Αποτέλεσμα = htClose έπειτα Msg. Αποτέλεσμα: = htNowhere;
Εάν ο χρήστης προσπαθεί να μετακινήσει τη φόρμα κάνοντας κλικ στη γραμμή υποτίτλων και σύροντάς τον, ο κώδικας αντικαθιστά το αποτέλεσμα του μηνύματος με ένα αποτέλεσμα που δείχνει ότι ο χρήστης έκανε κλικ στην περιοχή του πελάτη. Αυτό εμποδίζει τον χρήστη να μετακινεί το παράθυρο με το ποντίκι (αντίθετα από ό, τι κάναμε στην επαιτεία του άρθρου).
αν Msg. Αποτέλεσμα = htCaption έπειτα Msg. Αποτέλεσμα: = htClient;
Έχοντας τα στοιχεία σε μια φόρμα
Στις περισσότερες περιπτώσεις, θα έχουμε κάποια στοιχεία σε μια φόρμα. Ας πούμε, για παράδειγμα, ότι ένα αντικείμενο πίνακα βρίσκεται σε μια φόρμα. Αν η ιδιότητα Align του πίνακα έχει οριστεί σε alClient, ο πίνακας συμπληρώνει ολόκληρη την περιοχή πελάτη έτσι ώστε να είναι αδύνατο να επιλέξετε τη γονική φόρμα κάνοντας κλικ σε αυτήν. Ο παραπάνω κώδικας δεν θα λειτουργήσει - γιατί; Είναι επειδή το ποντίκι κινείται πάντοτε πάνω στο στοιχείο του πίνακα, όχι στη φόρμα.
Για να μετακινήσετε τη φόρμα μας μεταφέροντας ένα πλαίσιο στη φόρμα, πρέπει να προσθέσετε μερικές γραμμές κώδικα στη διαδικασία συμβάντος OnMouseDown για το στοιχείο Πάνελ:
διαδικασία TForm1.Panel1MouseDown
(Αποστολέας: TObject; Κουμπί: TMouseButton;
Μετατόπιση: TShiftState; X, Y: ακέραιος αριθμός).
ξεκινήσει
ReleaseCapture;
Αποστολή μηνύματος (Form1.Handle, WM_SYSCOMMAND, 61458, 0);
τέλος;
Σημείωση: Αυτός ο κώδικας δεν θα λειτουργήσει με στοιχεία ελέγχου χωρίς παράθυρο, όπως TLabel συστατικά.