wubba Posted March 28, 2011 Share Posted March 28, 2011 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? Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 28, 2011 Moderators Share Posted March 28, 2011 wubba, Welcome to the AutoIt forum. Why not make the child an MDI child and then let Windows look after it for you: #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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
martin Posted March 28, 2011 Share Posted March 28, 2011 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. Link to comment Share on other sites More sharing options...
wubba Posted March 29, 2011 Author Share Posted March 29, 2011 (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 March 29, 2011 by wubba Link to comment Share on other sites More sharing options...
wubba Posted March 29, 2011 Author Share Posted March 29, 2011 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. Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted March 29, 2011 Moderators Share Posted March 29, 2011 wubba,That was fun! Just put the title bar of the child over the "sticky area": expandcollapse popup#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 ;==>_GetRelPosA 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 Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
martin Posted March 29, 2011 Share Posted March 29, 2011 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! expandcollapse popup#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. Link to comment Share on other sites More sharing options...
wubba Posted March 30, 2011 Author Share Posted March 30, 2011 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. Link to comment Share on other sites More sharing options...
martin Posted March 30, 2011 Share Posted March 30, 2011 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 statementGUIRegisterMsg($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. jaberwacky 1 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. Link to comment Share on other sites More sharing options...
wubba Posted March 30, 2011 Author Share Posted March 30, 2011 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. Link to comment Share on other sites More sharing options...
martin Posted March 30, 2011 Share Posted March 30, 2011 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. Link to comment Share on other sites More sharing options...
wubba Posted March 31, 2011 Author Share Posted March 31, 2011 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. Link to comment Share on other sites More sharing options...
wubba Posted March 31, 2011 Author Share Posted March 31, 2011 (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 March 31, 2011 by wubba Link to comment Share on other sites More sharing options...
martin Posted March 31, 2011 Share Posted March 31, 2011 (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 expandcollapse popup#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 March 31, 2011 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. Link to comment Share on other sites More sharing options...
wubba Posted April 3, 2011 Author Share Posted April 3, 2011 Perfect. That's it. Thanks a lot. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now