Results 1 to 13 of 13

Thread: Moving a Form

  1. #1

    Thread Starter
    Lively Member
    Join Date
    Mar 2000
    Location
    Germany
    Posts
    84
    Hello,

    for a program I'm currently working on, I need to know, when my form is moved.
    I haven't been able to find a solution (event, which indicates that my form is being/was moved) so far, although I've been looking around on the Internet and MSDN.

    Maybe anyone of you can give me any tips??
    Thanks

  2. #2
    Fanatic Member RealisticGraphics's Avatar
    Join Date
    Jul 1999
    Location
    Arkansas
    Posts
    655

    Wink

    Put this is a module:

    Code:
    Global FormTop As Integer
    Global FormLeft As Integer
    
    Public Function HasFormMoved()
    If Form1.Top <> FormTop Or Form1.Left <> FormLeft Then
        'Do something if it has been moved
        MsgBox "Form has been moved"
        'reset values if you'd like
        FormTop = Form1.Top
        FormLeft = Form1.Left
    Else
        'Do something if it hasn't been moved
        MsgBox "Form has not been moved"
    End If
    End Function
    Put this in your form_load event:

    Code:
    FormTop = Form1.Top
    FormLeft = Form1.Left
    Whenever you want to know if your form has moved, just call the HasFormMoved function.

  3. #3

    Thread Starter
    Lively Member
    Join Date
    Mar 2000
    Location
    Germany
    Posts
    84
    that's not really what I need ...
    but thanks for trying to help me

    the program consists of 2 forms which are displayed together (I can't put into just one form), next to each other ...

    ... so when one form is moved, I want the other form to be moved too, and placed directly next to the first form

    ... as there is no FormMove event I'm looking for some code which tells when the form is moved


  4. #4
    Guest
    how would that work?
    how would you call it, when the form was moved?
    you would have to put it in a form_move event, one does not exist...

  5. #5
    Lively Member
    Join Date
    Mar 2000
    Posts
    103
    Just use the code posted above, but you would add code to move your second form whenever the first form is moved. If you want the second form right next to the first form on it's right had side then just do this:

    'add this to the code above

    frmSecond.Left = frmFirst.left + frmFirst.width
    frmSecond.Top = frmFirst.Top


    this will attach the second form to the right hand side of the first form.

  6. #6
    Fanatic Member RealisticGraphics's Avatar
    Join Date
    Jul 1999
    Location
    Arkansas
    Posts
    655

    Unhappy

    Well... Off the top of my head I cann't think of anything that would be super affective. You could use a timer to check on the form position using the same code I gave you however it would not be real accurate and it would each memory. Give me a few minutes and I'll what I kind find for you.

  7. #7
    Lively Member
    Join Date
    Mar 2000
    Posts
    103
    Response to Dennis' question:

    You would just stick it into a do until loop.

    Public Sub CheckForMovement()


    do until HasFormMoved

    doevents

    loop

    'can write code here to do stuff if the form has moved.


    'then call the sub recursively
    CheckForMovement

    end sub


  8. #8
    Fanatic Member RealisticGraphics's Avatar
    Join Date
    Jul 1999
    Location
    Arkansas
    Posts
    655
    denniswrenn:

    That code works fine as long as it doesn't need to be an instantanious change. I've used it before to save the position to the registry and to open other windows in relation to that window. But you're right, we need a form_move event.

  9. #9

    Thread Starter
    Lively Member
    Join Date
    Mar 2000
    Location
    Germany
    Posts
    84
    I know, I really would like to avoid using a timer...

    ... I found something about hooks just a few minutes ago - with them I should be able to do it ... but I haven't been using the API a lot ... only easy functions
    ... so right now I don't really know what to do ... but I'm working on it

    maybe anyone of you knows a little bit about it???


  10. #10
    Guest
    Does your form use a title bar? If you use a label to move the form, you can easily detect if its moving .

  11. #11
    Guru Yonatan's Avatar
    Join Date
    Apr 1999
    Location
    Israel
    Posts
    892

    Arrow You can create a SubClass.

    This is kinda tough to explain (so just accept it!), and it may crash if you debug your code and press the End button from the toolbar, or if you use the End statement anywhere in your code.
    Form code:
    Code:
    Option Explicit
    
    Private Sub Form_Load()
        Call HookUsUpScotty
    End Sub
    
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
        Call HookUsDownScotty
    End Sub
    
    Public Sub Form_FormMove()
        ' What??? FormMove???
        ' Yes!!! Woo hoo!!!
        ' Just leave it as a Public Sub, will you? This one doesn't like being Private.
    End Sub
    Don't get excited yet. This lovely module code will work if the above form is called Form1, but that can easily be changed.
    Code:
    Option Explicit
    
    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
    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 = (-4)
    
    Public Const WM_MOVE = &H3
    Public Const WM_MOVING = &H216
    
    Dim lpfnPrevWndProc As Long
    
    Public Sub HookUsUpScotty()
        lpfnPrevWndProc = SetWindowLong(Form1.hWnd, GWL_WNDPROC, AddressOf WindowProc)
    End Sub
    
    Public Sub HookUsDownScotty()
        Call SetWindowLong(Form1.hWnd, GWL_WNDPROC, lpfnPrevWndProc)
    End Sub
    
    Public Function WindowProc(ByVal hWnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        If (uMsg = WM_MOVE) Or (uMsg = WM_MOVING) Then Call Form1.Form_FormMove
        WindowProc = CallWindowProc(lpfnPrevWndProc, hWnd, uMsg, wParam, lParam)
    End Function
    I HAVEN'T TESTED IT! So I am not sure whether or not it works. But I think it does.

  12. #12

    Thread Starter
    Lively Member
    Join Date
    Mar 2000
    Location
    Germany
    Posts
    84

    Smile

    Hi Yonatan,
    thanks for your help.
    Yesterday evening I was also able to find something that works - even if I don't exactly how ...
    On the website of VbAccelerator is an example, using Windows Hooks, for keystrokes and mouse moves.
    I modified it a little so now it works quite well for my purpose.

    Code:
    Option Explicit
    
    Implements IWindowsHook
    
    Private Type POINTAPI
       x As Long
       y As Long
    End Type
    
    Dim xi, yi As Long
    '-----------------------
    Private Function IWindowsHook_HookProc(ByVal eType As EHTHookTypeConstants, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long, bConsume As Boolean) As Long
       Dim ctlOver As Control
       Dim bS As Boolean
       Dim lC As Long
       Dim lhWNd As Long
       Dim bSkip As Boolean
       Static ctlIgnore As Control
    
       With MouselParam(lParam)
          Select Case wParam
             Case WM_MOUSEMOVE
                If Me.Left <> xi Or Me.Top <> yi Then
                   If frKalibrBericht.Visible Then
                      frKalibrBericht.Left = Me.Left
                      frKalibrBericht.Top = Me.Top
                   End If
                   If frKalibrSet.Visible Then
                      frKalibrSet.Left = Me.Left
                      frKalibrSet.Top = Me.Top
                   End If
                   If frStammDatenShow.Visible Then
                      frStammDatenShow.Left = Me.Left - frStammDatenShow.Width
                      frStammDatenShow.Top = Me.Top
                   End If
                End If
                xi = Me.Left
                yi = Me.Top
       
             Case WM_LBUTTONUP, WM_LBUTTONDOWN
                xi = Me.Left
                yi = Me.Top
          End Select
       End With
    End Function
    '-----------------------
    Private Sub Form_Load()
       xi = Me.Left
       yi = Me.Top
       
       InstallHook Me, WH_MOUSE
    End Sub
    '-----------------------
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
       RemoveHook Me, WH_MOUSE
    End Sub
    You just need to have their DLL in your system32 directory
    (http://vbaccelerator.com/codelib/hook/vbalhook.htm)

  13. #13
    Guru Yonatan's Avatar
    Join Date
    Apr 1999
    Location
    Israel
    Posts
    892

    Thumbs down Do you really want to use a DLL?

    I always hate distributing any kind of DLL with my applications. If you want that exact same code with no DLL requirement, try this:
    Form code:
    Code:
    Option Explicit
    
    Private Sub Form_Load()
        xi = Left
        yi = Top
        
        Call InstallHook
    End Sub
    
    Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
        Call RemoveHook
    End Sub
    Module code:
    Code:
    Option Explicit
    
    Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
    Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
    Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
    
    Public Const WH_MOUSE = 7
    
    Public Const WM_MOUSEMOVE = &H200
    Public Const WM_LBUTTONDOWN = &H201
    Public Const WM_LBUTTONUP = &H202
    
    Dim hHook As Long
    
    Public xi As Long, yi As Long
    
    Public Sub InstallHook()
        hHook = SetWindowsHookEx(WH_MOUSE, AddressOf MouseProc, App.hInstance, App.ThreadID)
    End Sub
    
    Public Sub RemoveHook()
        Call UnhookWindowsHookEx(hHook)
    End Sub
    
    ' The "ByVal lParam As Long" should really be "lParam As MOUSEHOOKSTRUCT"
    ' but we don't need to access lParam so we can just use a pointer and skip the type declarations.
    Public Function MouseProc(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Select Case wParam
        Case WM_MOUSEMOVE
            ' Replace Form1 with the naForm1 of the form
            ' in which you put the code from the beginning of this post.
            If Form1.Left <> xi Or Form1.Top <> yi Then
                If frKalibrBericht.Visible Then
                    frKalibrBericht.Left = Form1.Left
                    frKalibrBericht.Top = Form1.Top
                End If
                If frKalibrSet.Visible Then
                    frKalibrSet.Left = Form1.Left
                    frKalibrSet.Top = Form1.Top
                End If
                If frStammDatenShow.Visible Then
                    frStammDatenShow.Left = Form1.Left - frStammDatenShow.Width
                    frStammDatenShow.Top = Form1.Top
                End If
            End If
            xi = Form1.Left
            yi = Form1.Top
        Case WM_LBUTTONUP, WM_LBUTTONDOWN
            xi = Form1.Left
            yi = Form1.Top
        End Select
        ' If lParam wasn't a Long pointer, then the ByVal wouldn't have been here:
        MouseProc = CallNextHookEx(hHook, nCode, wParam, ByVal lParam)
    End Function

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width