Sign in to follow this  
Followers 0
wubba

Detect window drag

15 posts in this topic

The title says it: I need some help with detecting window-movement.

I wanna automatically move a child window when its parent window is dragged somewhere. The (always smaller) child-window shall be "sticked" on the main window when its position is within the parents window's rectangle (no problem - window-position + size). Therefore I need autoit to find out when a window get's moved (during movement, not afterwards). Suggestions?

Share this post


Link to post
Share on other sites



wubba,

Welcome to the AutoIt forum. :)

Why not make the child an MDI child and then let Windows look after it for you: :P

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$hGUI_Parent = GUICreate("Parent", 500, 500)
GUISetState()

$hGUI_Child = GUICreate("Child", 200, 200, 150, 100, $GUI_SS_DEFAULT_GUI, $WS_EX_MDICHILD, $hGUI_Parent)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Does that do it for you? :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

Or if you want the child window to be a real child window which can't escape from its parent then you could do this

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <winapi.au3>

$hGUI_Parent = GUICreate("Parent", 500, 500)
GUISetState()

$hGUI_Child = GUICreate("Child", 200, 200, 10, 20,  BitOr($WS_MAXIMIZEBOX,$GUI_SS_DEFAULT_GUI))
GUISetState()
_WinAPI_SetParent($hGUI_Child, $hGUI_Parent);child will be at the position shifted from screen to parent client.

While 1
    $Msg = GUIGetMsg(1)
    Switch $Msg[0]
        Case $GUI_EVENT_CLOSE
            If $Msg[1] = $hGUI_Child Then
                GUIDelete($hGUI_Child)
            Else
                Exit
            EndIf
    EndSwitch
WEnd

Though I think you need to use OnEvent mode to be able to close the parent while there are still children.:)


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Thank you melba,

your suggestion seems to be very close to my idea. I use the Toolwindow-style and with the BitOr-Command I could combine it with the MDI-style and without getting unexpected results.

Line 6 looks this way now:

$hGUI_Child = GUICreate("Child", 200, 200, 150, 100, $GUI_SS_DEFAULT_GUI, BitOR ($WS_EX_TOOLWINDOW,$WS_EX_MDICHILD),$hGUI_Parent)

However, I want the child to stick on the parent only when being in the rectangle. Or even better: Only when covering a certain area inside.

Maybe I could change the style from

Bitor($WS_EX_MDICHILD, $WS_EX_TOOLWINDOW)
to
$WS_EX_TOOLWINDOW
when the child doesn't cover a specific area within the parent-window. Even found a command for that: "GUISetStyle". I will try that at a later time and maybe post the result here for further use. Edited by wubba

Share this post


Link to post
Share on other sites

Just tried it but it doesn't work. Can't find the mistake:

#include <GUIConstantsEx.au3> 
#include <WindowsConstants.au3> 
#include <GDIPlus.au3>
;Opt('MustDeclareVars', 1)

$hGUI_Parent = GUICreate("Parent", 400, 400)
GUISetState() 
$hlabel=GUICtrlCreateLabel(" Sticky area ",50,20,300,50)
GUICtrlSetBkColor ($hlabel,900000)
$hGUI_Child = GUICreate("Child", 200, 200, 150, 100, $GUI_SS_DEFAULT_GUI,$WS_EX_TOOLWINDOW,$hGUI_Parent) 
GUISetState() 
$hlabelstats=GUICtrlCreateLabel ("Window-Positions: ",50,50,100,100)


While 1 
    Switch GUIGetMsg()         
    case $GUI_EVENT_PRIMARYUP
        $parentpos = WinGetPos($hGUI_Parent)
        $childpos = WinGetPos($hGUI_Child)
        GUICtrlSetData($hlabelstats, "Parent-Pos: X: ", $parentpos[0] & " Y: " & $parentpos[1] & Chr(13) & Chr(13) & "Child-Pos: X: " & $childpos[0] & " Y: " & $childpos[1])
        
        ;X position
        If $Childpos[0] >= $parentpos[0] AND $childpos[0] <= $parentpos[0]+350 Then
            ;Y-Position
            If $childpos[1] >= $parentpos[1] AND $childpos[1] <= $parentpos[1]+70 Then
            GUISetStyle (Bitor($WS_EX_MDICHILD, $WS_EX_TOOLWINDOW),$hGUI_Child)
        EndIf
        Else 
            GUISetStyle ($WS_EX_TOOLWINDOW,$hGUI_Child)
        EndIf
    Case $GUI_EVENT_CLOSE             
        Exit     
    EndSwitch 
WEnd

The area is not sticky but it changes the style as soon as the child covers it. Unfortunately Bitor doesn't seem to work anymore here. Making it worse, the win-positions don't get printed into the label for some reason. I know there was something with screen-/window-relative coordinates which should't be confused when using window-positions, but I don't remember it anymore. Would be glad for help.

Share this post


Link to post
Share on other sites

wubba,

That was fun! :D

Just put the title bar of the child over the "sticky area": :P

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global Const $WM_ENTERSIZEMOVE = 0x231
Global $aRelPos[2]

$hGUI_Parent = GUICreate("Parent", 400, 400)
GUISetState()
$hlabel = GUICtrlCreateLabel(" Sticky area ", 50, 20, 300, 50)
GUICtrlSetBkColor($hlabel, 900000)
$hGUI_Child = GUICreate("Child", 200, 200, 150, 100)
GUISetState()
WinSetOnTop($hGUI_Child, "", 1)

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_PRIMARYUP
            $aLabel_Pos = WinGetPos(GUICtrlGetHandle($hlabel))
            $aChild_Pos = WinGetPos($hGUI_Child)

            ; Check for overlap
            If $aChild_Pos[0] > $aLabel_Pos[0] And ($aChild_Pos[0] + $aChild_Pos[2]) < ($aLabel_Pos[0] + $aLabel_Pos[1]) Then
                If $aChild_Pos[1] > $aLabel_Pos[1] And $aChild_Pos[1] < ($aLabel_Pos[1] + $aLabel_Pos[3]) Then
                    ; Allow the handlers to function
                    GUIRegisterMsg($WM_ENTERSIZEMOVE, "_GetRelPos")
                    GUIRegisterMsg($WM_MOVE, "_FollowMe")
                Else
                    ; Cancel the handlers
                    GUIRegisterMsg($WM_ENTERSIZEMOVE, "")
                    GUIRegisterMsg($WM_MOVE, "")
                EndIf
            Else
                ; Cancel the handlers
                GUIRegisterMsg($WM_ENTERSIZEMOVE, "")
                GUIRegisterMsg($WM_MOVE, "")
            EndIf

        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

; When the parent windoe moves move the child as well
Func _FollowMe($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam, $lParam

    If $hWnd <> $hGUI_Parent Then Return

    Local $aGUI_Parent_Pos = WinGetPos($hGUI_Parent) ; Use WinGetPos and not $lParam values
    WinMove($hGUI_Child, "", $aGUI_Parent_Pos[0] - $aRelPos[0], $aGUI_Parent_Pos[1] - $aRelPos[1])

EndFunc   ;==>_FollowMe

; When the parent window starts moving get the relative position of the child window.
Func _GetRelPos($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam, $lParam

    If $hWnd <> $hGUI_Parent Then Return

    Local $aGUI_Parent_Pos = WinGetPos($hGUI_Parent)
    Local $aGUI_Child_Pos = WinGetPos($hGUI_Child)

    $aRelPos[0] = $aGUI_Parent_Pos[0] - $aGUI_Child_Pos[0]
    $aRelPos[1] = $aGUI_Parent_Pos[1] - $aGUI_Child_Pos[1]

EndFunc   ;==>_GetRelPos

A bit rough and ready, but it proves the concept. :)

Does this fit the bill? :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

I like that Melba23, but the child doesn't get stuck to the parent when the parent is moved so that the child is in the sticky area again.

This can be done by a complicated simplification!

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global Const $WM_ENTERSIZEMOVE = 0x231
Global $aRelPos[2], $aChild_Pos[4], $difx, $dify,$lock = False
$hGUI_Parent = GUICreate("Parent", 400, 400)
GUISetState()

$hlabel = GUICtrlCreateLabel(" Sticky area ", 50, 20, 300, 50)
GUICtrlSetBkColor($hlabel, 900000)
$hGUI_Child = GUICreate("Child", 200, 200, 150, 100)
GUISetState()
WinSetOnTop($hGUI_Child, "", 1)
GUIRegisterMsg($WM_ENTERSIZEMOVE, "_GetRelPos")
GUIRegisterMsg($WM_MOVE, "_FollowMe")
$aLabel_Pos = WinGetPos(GUICtrlGetHandle($hlabel))
ConsoleWrite($aLabel_Pos[0] & ', ' & $aLabel_Pos[1] & @CRLF)

While 1
    Switch GUIGetMsg()

        ;Case $GUI_EVENT_PRIMARYDOWN
        ;   $lock = False

        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

; When the parent window moves move the child as well
Func _FollowMe($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam, $lParam

    If $hWnd <> $hGUI_Parent Then Return

    $aLabel_Pos = WinGetPos(GUICtrlGetHandle($hlabel))
    If Not $lock Then
        $aChild_Pos = WinGetPos($hGUI_Child)
        $difx = $aChild_Pos[0] - $aLabel_Pos[0]
        $dify = $aChild_Pos[1] - $aLabel_Pos[1]
    EndIf
    ConsoleWrite($aLabel_Pos[0] & ', ' & $aLabel_Pos[1] & @CRLF)
    ConsoleWrite($aChild_Pos[0] & ', ' & $aChild_Pos[1] & @CRLF)
    If $lock or ($aChild_Pos[0] > $aLabel_Pos[0] And ($aChild_Pos[0]) < ($aLabel_Pos[0] + $aLabel_Pos[2]) And _
            $aChild_Pos[1] > $aLabel_Pos[1] And $aChild_Pos[1] < ($aLabel_Pos[1] + $aLabel_Pos[3])) Then

        $lock = True
        WinMove($hGUI_Child, "", $aLabel_Pos[0] + $difx, $aLabel_Pos[1] + $dify)
    EndIf

EndFunc   ;==>_FollowMe

Func _GetRelPos($hWnd, $iMsg, $wParam, $lParam)
    $lock = false

EndFunc

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Thanks a lot melba,

It's exactly what I was looking for. How do I get the sticky-area always sticky? When moving the parent, the child sometimes follows and sometimes don't. I don't understand the code anymore. Did you register new event-handlers for this? What is "$WM_ENTERSIZEMOVE = 0x231" ? Is "$WM_MOVE" the event for a move-operation? I don't understand how the _followMe-function gets executed from the main-loop.

Sorry martin, in your version the child doesn't stick at all on the parent-window - at least not on my computer.

Share this post


Link to post
Share on other sites

Thanks a lot melba,

It's exactly what I was looking for. How do I get the sticky-area always sticky? When moving the parent, the child sometimes follows and sometimes don't. I don't understand the code anymore. Did you register new event-handlers for this? What is "$WM_ENTERSIZEMOVE = 0x231" ? Is "$WM_MOVE" the event for a move-operation? I don't understand how the _followMe-function gets executed from the main-loop.

Sorry martin, in your version the child doesn't stick at all on the parent-window - at least not on my computer.

The message WM_ENTERSIZEMOVE is sent when the window start a move. Every time the window position changes a WM_MOVE message is sent, (assuming you have Desktop|View|Effectes | show windows contents while dragging checked). When the move stops because the mouse button is released a message WM_EXITSIZEMOVE is sent.

By using the statement

GUIRegisterMsg($WM_MOVE, "_FollowMe")

it means the script will use the _FollowMe function every time the WM_MOVE message is received.

If you see the whole window move while you drag it then I don't know why the child window doesn't move with my version.

1 person likes this

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

That's it. Changing the windows-settings in xp made your script run. It's awesome and works perfectly now. Is there some way to detect window-movement in all cases? I can't expect other computers have the option enabled by default.

Share this post


Link to post
Share on other sites

That's it. Changing the windows-settings in xp made your script run. It's awesome and works perfectly now. Is there some way to detect window-movement in all cases? I can't expect other computers have the option enabled by default.

I'm glad you got it to work.

Unfortunately, when you are dragging a window not much can be done in a script, even timers don't work properly afaik. The only way I can think of is to start another script which monitors the window positions and moves the child with the parent when required.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

mmm...

Maybe a good workaround was changing the XP-settings for duration of the script-run. I bet tweaking some registry-entry would do the trick.

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

I found it:

In the registry under [HKEY_CURRENT_USER\Control Panel\Desktop]

the value "DragFullWindows" needs to get changed from 0 to 1.

Problem: No change in behavior. During movement, windows still show rectangles when the value was switched manually.

According to some forum-post, "using the supported API" would be better. Unfortunately my background-knowledge doesn't seem to be good enough to understand what they talk about in the recommended link. What do they use to call the parameters? Is this some special API-stuff? Can I use autoit to call the mentioned functions?

Edited by wubba

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

You can add this function then call it to turn the "show contents" on or off.

;=== _SetDragMode ============
;sets the grag mode for windows to show contents true or false.
;returns the previous setting
; by martin
Func _SetDragMode($Mode = True)
    Const $SPI_SETDRAGFULLWINDOWS = 0x0025, $SPI_GETDRAGFULLWINDOWS = 0x0026
    Const $SPIF_SENDWININICHANGE = 0x2, $SPIF_SENDCHANGE = 0x1

    Local $oldVal = DllStructCreate("int")
    Local $pOV = DllStructGetPtr($oldVal)
    _WinAPI_SystemParametersInfo($SPI_GETDRAGFULLWINDOWS, 0, $pOV, 0)

    _WinAPI_SystemParametersInfo($SPI_SETDRAGFULLWINDOWS, _
            $Mode, _
            0, _
            BitOr($SPIF_SENDCHANGE,$SPIF_SENDWININICHANGE))

    Return DllStructGetData($oldVal, 1)
EndFunc   ;==>_SetDragMode

EDIT

... and here is an example showing how to use it

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <winapi.au3>

Global $WinDrag = _SetDragMode(True)
OnAutoItExitRegister("whenYouGo")
Global Const $WM_ENTERSIZEMOVE = 0x231
Global $aRelPos[2], $aChild_Pos[4], $difx, $dify, $lock = False
$hGUI_Parent = GUICreate("Parent", 400, 400)
GUISetState()

$hlabel = GUICtrlCreateLabel(" Sticky area ", 50, 20, 300, 50)
GUICtrlSetBkColor($hlabel, 900000)
$hGUI_Child = GUICreate("Child", 200, 200, 150, 100)
GUISetState()
WinSetOnTop($hGUI_Child, "", 1)
GUIRegisterMsg($WM_ENTERSIZEMOVE, "_GetRelPos")
GUIRegisterMsg($WM_MOVE, "_FollowMe")
$aLabel_Pos = WinGetPos(GUICtrlGetHandle($hlabel))
ConsoleWrite($aLabel_Pos[0] & ', ' & $aLabel_Pos[1] & @CRLF)

While 1
    Switch GUIGetMsg()

        ;Case $GUI_EVENT_PRIMARYDOWN
        ;   $lock = False

        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch

WEnd

; When the parent window moves move the child as well
Func _FollowMe($hWnd, $iMsg, $wParam, $lParam)

    #forceref $iMsg, $wParam, $lParam

    If $hWnd <> $hGUI_Parent Then Return

    $aLabel_Pos = WinGetPos(GUICtrlGetHandle($hlabel))
    If Not $lock Then
        $aChild_Pos = WinGetPos($hGUI_Child)
        $difx = $aChild_Pos[0] - $aLabel_Pos[0]
        $dify = $aChild_Pos[1] - $aLabel_Pos[1]
    EndIf
    ConsoleWrite($aLabel_Pos[0] & ', ' & $aLabel_Pos[1] & @CRLF)
    ConsoleWrite($aChild_Pos[0] & ', ' & $aChild_Pos[1] & @CRLF)
    If $lock or ($aChild_Pos[0] > $aLabel_Pos[0] And ($aChild_Pos[0]) < ($aLabel_Pos[0] + $aLabel_Pos[2]) And _
            $aChild_Pos[1] > $aLabel_Pos[1] And $aChild_Pos[1] < ($aLabel_Pos[1] + $aLabel_Pos[3])) Then

        $lock = True
        WinMove($hGUI_Child, "", $aLabel_Pos[0] + $difx, $aLabel_Pos[1] + $dify)
    EndIf

EndFunc   ;==>_FollowMe

Func _GetRelPos($hWnd, $iMsg, $wParam, $lParam)
    $lock = False

EndFunc   ;==>_GetRelPos


;=== _SetDragMode ============
;sets the grag mode for windows to show contents true or false.
;returns the previous setting
; by martin
Func _SetDragMode($Mode = True)
    Const $SPI_SETDRAGFULLWINDOWS = 0x0025, $SPI_GETDRAGFULLWINDOWS = 0x0026
    Const $SPIF_SENDWININICHANGE = 0x2, $SPIF_SENDCHANGE = 0x1

    Local $oldVal = DllStructCreate("int")
    Local $pOV = DllStructGetPtr($oldVal)
    _WinAPI_SystemParametersInfo($SPI_GETDRAGFULLWINDOWS, 0, $pOV, 0)

    _WinAPI_SystemParametersInfo($SPI_SETDRAGFULLWINDOWS, _
            $Mode, _
            0, _
            BitOR($SPIF_SENDCHANGE, $SPIF_SENDWININICHANGE))

    Return DllStructGetData($oldVal, 1)
EndFunc   ;==>_SetDragMode

Func whenYouGo()

    _SetDragMode($WinDrag)

EndFunc   ;==>whenYouGo
Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Perfect. That's it. Thanks a lot.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0