Link to home
Start Free TrialLog in
Avatar of larrysy
larrysyFlag for Canada

asked on

synchronized window move

How do I move Form2 relative to Form1 automatically when I move Form1?

I have the following code which will move Form2 when I resize Form1, but I want to move Form2 when I move Form1 (something like Form_Move)

Private Sub Form_Load()
Form2.Show
End Sub

Private Sub Form_Resize()
Form2.Left = Me.Left
Form2.Top = Me.Top + Me.Height
End Sub
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of larrysy

ASKER

Thanks, it works.

Follow-up questions,
How do I prevent the error when I move Form1 after I minimize Form2?
Is there a way to dock Form2 to Form1 automatically when Form2 is in the vicinity of the docking area?

Avatar of larrysy

ASKER

I tried the following code in Form2 and it works, any loopholes?

Private Sub Form_Resize()
If Me.WindowState = 1 Then HookWindow Form1.hWnd
End Sub
Avatar of larrysy

ASKER

Another question:

I put the following code in Form1 for undocking - is it correct?

Private Sub Command2_Click()
HookWindow Me.hWnd
End Sub

However, if I click on Command1 again, the docking doesnt work.
' -------------------------------
' Form1
' -------------------------------
Option Explicit

Private Sub Form_Load()
    ' center the form
    Me.Left = (Screen.Width / 2) - (Me.Width / 2)
    Me.Top = (Screen.Height / 2) - (Me.Height / 2)
   
    ' subclass the window
    HookWindow Me.hWnd
End Sub

Private Sub Command1_Click()
    Form2.Move Form1.Left, Form1.Top + Form1.Height
    Form2.Show
End Sub

Private Sub Command2_Click()
    HookWindow Me.hWnd
    If lPrevProc <> 0 Then
        If Form2.WindowState = vbNormal And Form2.Visible Then
            Form2.Move Form1.Left, Form1.Top + Form1.Height
        End If
    End If
End Sub

Private Sub Form_Resize()
    If Me.WindowState = vbNormal And Me.Visible Then
        If Form2.WindowState = vbNormal And Form2.Visible Then
            Form2.Move Form1.Left, Form1.Top + Form1.Height
        End If
    End If
End Sub

Private Sub Form_Unload(Cancel As Integer)
    If lPrevProc <> 0 Then
        HookWindow Me.hWnd
    End If
End Sub

' -------------------------------
' Form2
' -------------------------------
Option Explicit

Private Sub Form_Resize()
    If Me.WindowState = vbNormal And Me.Visible Then
        If Form1.WindowState = vbNormal And Form1.Visible Then
            Me.Move Form1.Left, Form1.Top + Form1.Height
        End If
    End If
End Sub

' -------------------------------
' Module1
' -------------------------------
Option Explicit

Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
    (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal msg As Long, _
    ByVal wParam As Long, ByVal lParam As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
    (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public Const GWL_WNDPROC As Long = (-4)
Public Const WM_MOVING = &H216
Public Const WM_SIZING = &H214

Public lPrevProc As Long

Public Sub HookWindow(ByVal lHandle As Long)
    If lPrevProc = 0 Then
        lPrevProc = SetWindowLong(lHandle, GWL_WNDPROC, AddressOf HookProc)
    Else
        Call SetWindowLong(lHandle, GWL_WNDPROC, lPrevProc)
        lPrevProc = 0
    End If
End Sub

Public Function HookProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case uMsg
        Case WM_SIZING, WM_MOVING
            If Form2.WindowState = vbNormal And Form2.Visible Then
                Form2.Move Form1.Left, Form1.Top + Form1.Height
            End If
            HookProc = 1
            Exit Function
    End Select
   
    HookProc = CallWindowProc(lPrevProc, hWnd, uMsg, wParam, lParam)
End Function

>> Is there a way to dock Form2 to Form1 automatically when Form2 is in the vicinity of the docking area?

You would have to subclass Form2 exactly as we did with Form1.  Then when the sizing or moving messages fire, you would check Form2s location in relation to Form1s and if they are close enough, dock Form2 to Form1.

~IM
Avatar of larrysy

ASKER

Thanks, your code example is a big help!  

One final question, if you close Form1 without clicking any buttons, the program wont end properly but hangs in HookProc.  Any way to remedy this aside from using END ? Or, is it OK to use END?
Don't use the Stop button in the IDE when you have subclassed a form as this usually causes the IDE to crash.  Always provided a way to close your app somehow that will result in the form being unhooked properly.  When subclassing is involved, always save your work before running the application since any minor error can result in the IDE crashing.  Welcome to subclassing...  =\

~IM
Avatar of larrysy

ASKER

Thank you very much for your tiips !!

larry