|
Vielleicht programmieren Sie ja gerade eine Anwendung mit einem
wunderschönen Design Ihrer Forms - und die "hässliche"
Titelleiste stört Sie dabei gewaltig. Die Schaltflächen zum
Minimieren, Maximieren und Schließen des Forms würden Sie ja mit
CommandButtons einfach nachbilden können. Aber wie ermöglichen Sie
es dem Anwender, das Form weiterhin mit der Maus verschieben zu
können, wenn die Titelleiste fehlt? Oder möchten Sie es dem
Anwender ermöglichen, ein beliebiges Steuerelement, etwa eine
PictureBox, frei im Form verschieben zu können?
Das ist kein großes Problem. Denn glücklicherweise können wir
auf den gleichen Mechanismus zurückgreifen, den Windows im Prinzip
auch intern verwendet.
Die Titelleiste gehört aus der Sicht von Windows nicht mehr zum
Arbeitsbereich ("Client-Bereich") eines Forms
("Fensters") - das merken Sie ja auch daran, dass Sie dort
keine Steuerelemente platzieren können. Naheliegenderweise wird der
Bereich zwischen dem Client-Bereich und der eigentlichen
Fenster-Außenkante als "Non-Client-Bereich" bezeichnet,
und er wird von Windows auf eigene Weise verwaltet. So werden alle
Mausaktivitäten in diesem Bereich dem Fenster über spezielle
"Nachrichten" mitgeteilt (Die Funktionsweise dieses
Nachrichten-Systems hier zu erläutern, würde den Rahmen dieses
Beitrags sprengen - wenn es Sie näher interessiert, finden Sie in
der MSDN-Library
jede Menge Informationen darüber.).
Für unseren Zweck benötigen wir hier die Nachricht WM_NCLBUTTONDOWN.
Diese Nachricht wird immer dann an ein Fenster gesendet, wenn die
linke Maustaste in jenem Non-Client-Bereich niedergedrückt wird.
Dieser Bereich ist in mehrere Unterbereiche unterteilt. Uns
interessiert hier wiederum nur der Unterbereich, der von Windows so
identifiziert werden soll, als wenn es die Titelleiste ("Caption")
wäre. Wir simulieren also einfach das Klicken auf die Titelleiste.
Das Senden von Nachrichten an Windows erfolgt mit Hilfe der
API-Funktion SendMessage,
der neben dem Fenster-Handle (hWnd-Eigenschaft des zu verschiebenden
Forms oder Steuerelements) der Konstantwert der Nachricht selbst (WM_NCLBUTTONDOWN)
und der Konstantwert HTCAPTION
als weiterer Parameter übergeben werden.
Da wir ja den Non-Client-Bereich-Mausklick an einer Stelle
innerhalb des Client-Bereichs simulieren wollen, müssen wir Windows
zuvor ein wenig austricksen. Infolge der Mausbewegung über dem
Client-Bereich hat Windows den Mauszeiger sozusagen eingefangen, um
ihn verfolgen zu können ("Captured"). Im
MouseDown-Ereignis des zu verschiebenden Objekts rufen wir die
Hilfsfunktion MoveObject auf und übergeben ihr eine Referenz auf
das Objekt. In dieser Funktion weisen wir Windows mit dem Aufruf der
API-Funktion ReleaseCapture
als erstes an, den Mauszeiger aus der Aufsicht zu entlassen. Danach
folgt das Senden der Nachricht mit der SendMessage-Funktion - und
schon "klebt" das gewünschte Objekt so lange unter dem
Mauszeiger, bis der Anwender die Maustaste wieder los lässt.
Private Declare Function ReleaseCapture Lib "user32" () As Long
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, _
ByVal wParam As Long, lParam As Any) As Long
Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, _
Y As Single)
If Button = vbLeftButton Then
MoveObject Me
End If
End Sub
Sub MoveObject(Obj As Object)
Const WM_NCLBUTTONDOWN = &HA1
Const HTCAPTION = 2
ReleaseCapture
SendMessage Obj.hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0
End Sub
 |
Zum Verschieben eines Forms oder
Steuerelements gaukeln Sie Windows vor, der Anwender hätte
auf die Titelleiste geklickt

|

|