#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
$gui1 = GUICreate("Nummer 1", 300, 300)
$gui2 = GUICreate("Ich bin gedockt RECHTS", 200, 200, -1, -1, -1, $WS_EX_TOOLWINDOW)
$gui3 = GUICreate("Ich bin gedockt LINKS", 200, 200, -1, -1, -1, $WS_EX_TOOLWINDOW)
$gui4 = GUICreate("Ich bin gedockt UNTEN", 200, 200, -1, -1, -1, $WS_EX_TOOLWINDOW)

Global $aDocks[5][2] = [[$gui1,0],[$gui2,1],[$gui3,3],[$gui4,2],[-1]]
; [n][GUI,DockPos] - letztes Arrayelement ([Ubound($aDocks)-1][0]) speichert den Abstand
; dockPos: 1=rechts, 2=unten, 3=links, 4=oben
; Abstand: -1=SysMetrics Fensterrand, alle anderen Werte Pixelabstand zw. Fenstern

GUISetState(@SW_SHOW, $gui4)
GUISetState(@SW_SHOW, $gui3)
GUISetState(@SW_SHOW, $gui2)
GUISetState(@SW_SHOW, $gui1)

;== WM_MOVE registrieren:
GUIRegisterMsg($WM_MOVE, "WM_MOVE")


;== Fenster anordnen und Ereignis WM_MOVE auslösen zum erstmaligen Positionieren der Fenster
_ArrangeGUI()
_moved()

While True
    $msg = GUIGetMsg()
    Switch $msg
        Case -3
            Exit
    EndSwitch
WEnd

Func _ArrangeGUI($Index_Master=0)
	Local $iDiff, $aPos1, $aPos2
	If $aDocks[UBound($aDocks)-1][0] = -1 Then
		Local $ret = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 32)
		If IsArray($ret) Then $iDiff = $ret[0]
	Else
		$iDiff = $aDocks[UBound($aDocks)-1][0]
	EndIf
	If $Index_Master = 0 Then ; === Main-GUI bewegt
		$aPos1 = WinGetPos(WinGetHandle($aDocks[0][0]))
		For $i = 1 To UBound($aDocks) -2
			$aPos2 = WinGetPos(WinGetHandle($aDocks[$i][0]))
			Switch $aDocks[$i][1]
				Case 1
					WinMove($aDocks[$i][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1])
				Case 2
					WinMove($aDocks[$i][0], '', $aPos1[0], $aPos1[1]+$aPos1[3]+$iDiff)
				Case 3
					WinMove($aDocks[$i][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1])
				Case 4
					WinMove($aDocks[$i][0], '', $aPos1[0], $aPos1[1]-$iDiff-$aPos2[3])
			EndSwitch
		Next
	Else ; === Child bewegt ==> zuerst Main-GUI nachrücken
		$aPos1 = WinGetPos(WinGetHandle($aDocks[$Index_Master][0]))
		$aPos2 = WinGetPos(WinGetHandle($aDocks[0][0]))
		Switch $aDocks[$Index_Master][1]  ; Positionsflag entgegengesetz behandeln
			Case 3
				WinMove($aDocks[0][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1])
			Case 4
				WinMove($aDocks[0][0], '', $aPos1[0], $aPos1[1]+$aPos1[3]+$iDiff)
			Case 1
				WinMove($aDocks[0][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1])
			Case 2
				WinMove($aDocks[0][0], '', $aPos1[0], $aPos1[1]-$iDiff-$aPos2[3])
		EndSwitch
		_moved() ; === $WM_MOVE senden um andere Childs auszurichten
	EndIf
EndFunc

Func _moved()
    DllCall("User32.dll", "int", "PostMessageA", "hwnd", $aDocks[0][0], "int", $WM_MOVE, "int", 0, "int", 0)
EndFunc

Func WM_MOVE($hWndGUI)
	For $i = 0 To UBound($aDocks) -2
		If $hWndGUI = WinGetHandle($aDocks[$i][0]) Then Return _ArrangeGUI($i)
	Next
    Return $GUI_RUNDEFMSG
EndFunc

