Rubrik: Oberfläche · Fenster | VB-Versionen: VB5, VB6 | 02.08.04 |
FormMove- und FormBeforeMove-Ereignis in VB Per Subclassing lässt sich das in VB fehlende FormMove-Ereignis relativ leicht nachrüsten, sogar optional mit der Möglichkeit das Verschieben der Form zu unterbinden! | ||
Autor: Dieter Otter | Bewertung: | Views: 12.517 |
www.tools4vb.de | System: Win9x, WinNT, Win2k, WinXP, Win7, Win8, Win10, Win11 | Beispielprojekt auf CD |
Immer wieder wird in unserem Diskussionsforum die Frage gestellt: "Warum gibt es in VB keine Benachrichtigung, wenn eine Form verschoben wird und wie kann ich dennoch ermitteln, wann eine Form verschoben wird?"
Die Lösung für hierzu lautet wie so oft: Subclassing der Form, d.h. man muss die Fensternachrichten von Windows "abhorchen". Und wenn wir schon beim "Abhören" der Fensternachrichten sind: was würde näher liegen, als bspw. dann sogar das Verschieben des Fensters zu unterbinden?
Fügen Sie dem Projekt ein neues Modul mit folgendem Code hinzu:
Option Explicit ' benötigte API's Private Declare Function SetWindowLong Lib "user32.dll" _ Alias "SetWindowLongA" ( _ ByVal hwnd As Long, _ ByVal nIndex As Long, _ ByVal dwNewLong As Long) As Long Private Declare Function CallWindowProc Lib "user32.dll" _ Alias "CallWindowProcA" ( _ ByVal lpPrevWndFunc As Long, _ ByVal hwnd As Long, _ ByVal Msg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Private Declare Function ReleaseCapture Lib "user32" () As Long Private Const GWL_WNDPROC As Long = -4 Private Const WM_MOVE = &H3 Private Const WM_MOVING = &H216 Private PrevWndProc As Long Private oForm As Form
' Fensternachrichten an die Prozedur WndProc "umleiten" Public Function InitSubclassing(Form As Object) As Long Set oForm = Form PrevWndProc = SetWindowLong(oForm.hwnd, _ GWL_WNDPROC, AddressOf WndProc) End Function
' Subclassing beenden Public Sub EndSubclassing(Form As Object) Call SetWindowLong(oForm.hwnd, GWL_WNDPROC, PrevWndProc) Set oForm = Nothing End Sub
' Hier kommen alle Fensternachrichten an Public Function WndProc(ByVal hwnd As Long, _ ByVal Msg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As Long Static bNoMoveEvent As Boolean Dim bCancel As Boolean On Error Resume Next If Msg = WM_MOVING Then ' Meldung an die Form schicken, ' dass das Fenster verschoben werden soll bCancel = False oForm.FormBeforeMove bCancel If bCancel Then ' Nachricht als "verarbeitet" kennzeichnen, ' um das Verschieben zu verhindern bNoMoveEvent = True ReleaseCapture WndProc = 1 Exit Function Else bNoMoveEvent = False End If ElseIf Msg = WM_MOVE Then ' Fenster wurde verschoben ' Meldung an die Form weiterleiten If Not bNoMoveEvent Then oForm.FormMove End If End If ' Nachricht an die Original-Fensterprozedur weiterleiten WndProc = CallWindowProc(PrevWndProc, hwnd, Msg, wParam, ByVal lParam) End Function
Damit die Form selbst über die Nachricht "Achtung! Fenster soll verschoben werden!" oder "Achtung! Fenster wurde verschoben" benachrichtigt werden kann, müssen nachfolgende Prozeduren als öffentliche Prozeduren in den Codeteil der Form eingefügt werden:
Public Sub FormBeforeMove(bCancel As Boolean) Debug.Print "Form soll verschoben werden" ' Um das Verschieben der Form zu unterbinden ' einfach den Parameter bCancel = True setzen ' bCancel = True End Sub
Public Sub FormMove() Debug.Print "Fenster wird verschoben!" End Sub
Damit die Fensternachrichten abgehört werden können, muss beim Laden der Form das "Subclassing" gestartet werden. Wichtig ist auch das korrekte Beenden des Subclassings - am besten im Form_QueryUnload-Ereignis.
Private Sub Form_Load() ' Subclassing starten InitSubclassing Me End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) ' Wichtig! Subclassing beenden EndSubclassing Me End Sub