#cs
===== Funktionsübersicht =====
_GUIDock_StartUp($hWnd)
	Initialisiert notwendige Variablen
	$hWnd bekommt Status MainWindow
	registriert ShutDown-Funktion

_GUIDock_DockWindow($vWnd [, $vAlign])
	Einzelnes (oder Array mit mehreren) GUI-Hwnd andocken
	Werden Anordnung und Ausrichtung NICHT in $vAlign übergeben, muß dieses anschließend mit _GUIDock_SetAlignment ausgeführt werden
	Bei Übergabe eines einzelnen Hwnd ist $vAlign vorbelegt mit Rechts-Oben

_GUIDock_UnDockWindow($vWnd)
	Einzelnes (oder Array mit mehreren) GUI-Hwnd abdocken

_GUIDock_SetDistance($iDistance=-1)
	Abstand zwischen Main-GUI und gedockten Fenstern.
	Standard ist die Borderbreite aus den Systemmetrics

_GUIDock_SetAlignment($hWnd, $iAlign)
	Fensteranordnung + Ausrichtung durch BitOr-Verknüpfung folgender Konstanten:

	Andocken rechts	$_GUI_DOCK_RIGHT
	Andocken unten	$_GUI_DOCK_BOTTOM
	Andocken links	$_GUI_DOCK_LEFT
	Andocken oben	$_GUI_DOCK_TOP

	Ausrichten links oder oben		$_GUI_ALIGN_LEFTorTOP
	Ausrichten zentriert			$_GUI_ALIGN_CENTER
	Ausrichten rechts oder unten	$_GUI_ALIGN_RIGHTorBOTTOM
#ce
;===================================================================================================
;                                   Version 1.1 - 15.10.2010                                       ;
;===================================================================================================

#include-once
#include <WindowsConstants.au3>
#include <Array.au3>
#include <Constants.au3>
#include <WinAPI.au3>

#region - Deklarationen
Global Const $_GUI_DOCK_RIGHT          = 1
Global Const $_GUI_DOCK_BOTTOM         = 2
Global Const $_GUI_DOCK_LEFT           = 4
Global Const $_GUI_DOCK_TOP            = 8
Global Const $_GUI_ALIGN_LEFTorTOP     = 16
Global Const $_GUI_ALIGN_CENTER        = 32
Global Const $_GUI_ALIGN_RIGHTorBOTTOM = 64

Global $ahProcHook[1], $aGUIDocks[2][2] = [[0,0],[-1]], $iDockDistance
Global $hProcDock = DllCallbackRegister('__WndProc', 'ptr', 'hwnd;uint;wparam;lparam')
#endregion

#region - UDF
;===============================================================================
; Function Name:   _GUIDock_StartUp($hWnd)
; Description:     	Initialisiert notwendige Variablen, $hWnd bekommt Status MainWindow
; Parameter(s):    $hWnd	Fenster an dem die anderen angedockt werden
; Author(s):       BugFix (bugfix@autoit.de)
;===============================================================================
Func _GUIDock_StartUp($hWnd)
	Local $ret = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 32)
	If IsArray($ret) Then $iDockDistance = $ret[0]
	$aGUIDocks[0][0] = $hWnd
	OnAutoItExitRegister('__GUIDock_ShutDown')
	; Array-Hook erstellen! => für jedes Fenster ein Hook
	$ahProcHook[0] = _WinAPI_SetWindowLong($hWnd, $GWL_WNDPROC, DllCallbackGetPtr($hProcDock))
EndFunc  ;==>_GUIDock_StartUp

;===============================================================================
; Function Name:   _GUIDock_DockWindow($vWnd, $vAlign=Default)
; Description:    	Einzelnes oder mehrere GUI andocken (optional gleich ausrichten)
; Parameter(s):    $vWnd	Einzelnes (oder Array mit mehreren) GUI-Hwnd
;     optional:    $vAlign	Einzelner (oder Array mit mehreren) BitOr -Wert für Anordnung+Ausrichtung
;                           Bei Einzelübergabe ist er standardmäßig auf Rechts-Oben gesetzt
;                           Wenn nicht übergeben, zwingend _GUIDock_SetAlignment ausführen
; Author(s):       BugFix (bugfix@autoit.de)
;===============================================================================
Func _GUIDock_DockWindow($vWnd, $vAlign=Default)
	If IsKeyword($vAlign) Then $vAlign = BitOR($_GUI_DOCK_RIGHT,$_GUI_ALIGN_LEFTorTOP)
	If Not IsArray($vWnd) Then
		Local $tmpArray[1] = [$vWnd]
		$vWnd = $tmpArray
	EndIf
	If Not IsArray($vAlign) Then
		Local $tmpArray[1] = [$vAlign]
		$vAlign = $tmpArray
	EndIf
	If UBound($vAlign) < UBound($vWnd) Then ReDim $vAlign[UBound($vWnd)]
	Local $tmpDist = $aGUIDocks[UBound($aGUIDocks)-1][0]
	Local $iUb = UBound($aGUIDocks), $j = 0
	ReDim $aGUIDocks[$iUb+UBound($vWnd)][2]
	ReDim $ahProcHook[UBound($ahProcHook)+UBound($vWnd)]
	For $i = $iUb-1 To UBound($aGUIDocks) -2
		$aGUIDocks[$i][0] = $vWnd[$j]
		$aGUIDocks[$i][1] = $vAlign[$j]
		$ahProcHook[$i] = _WinAPI_SetWindowLong($vWnd[$j], $GWL_WNDPROC, DllCallbackGetPtr($hProcDock))
		$j += 1
	Next
	$aGUIDocks[UBound($aGUIDocks)-1][0] = $tmpDist
	__moved()
EndFunc  ;==>_GUIDock_DockWindow

;===============================================================================
; Function Name:   _GUIDock_UnDockWindow($vWnd)
; Description:     Einzelnes oder mehrere GUI abdocken
; Parameter(s):    $vWnd	Einzelnes (oder Array mit mehreren) GUI-Hwnd
; Author(s):       BugFix (bugfix@autoit.de)
;===============================================================================
Func _GUIDock_UnDockWindow($vWnd)
	If Not IsArray($vWnd) Then
		Local $tmpArray[1] = [$vWnd]
		$vWnd = $tmpArray
	EndIf
	Local $index
	For $i = 0 To UBound($vWnd) -1
		$index = _ArraySearch($aGUIDocks, $vWnd[$i], 1, UBound($aGUIDocks)-2)
		If @error Then ContinueLoop
		_WinAPI_SetWindowLong($aGUIDocks[$index][0], $GWL_WNDPROC, $ahProcHook[$index]) ; UnHook GUI
		_ArrayDelete($ahProcHook, $index) ; Hook-hwnd löschen
		_ArrayDelete($aGUIDocks, $index) ; GUI-hwnd löschen
	Next
EndFunc  ;==>_GUIDock_UnDockWindow

;===============================================================================
; Function Name:   _GUIDock_SetDistance($iDistance=-1)
; Description:     	Abstand zwischen Main-GUI und gedockten Fenstern setzen
; Parameter(s):    $iDistance	Abstand in Pixel, Standard ist die Borderbreite aus den Systemmetrics
; Author(s):       BugFix (bugfix@autoit.de)
;===============================================================================
Func _GUIDock_SetDistance($iDistance=-1)
	$aGUIDocks[UBound($aGUIDocks)-1][0] = $iDistance
EndFunc  ;==>_GUIDock_SetDistance

;===============================================================================
; Function Name:   _GUIDock_SetAlignment($hWnd, $iAlign=Default)
; Description:     Anordnung + Ausrichtung des gedockten Fensters zur Main-GUI
; Parameter(s):    $hWnd	das gedockte Fenster
;                  $iAlign  BitOr-Verknüpfung aus folgenden Konstanten:
;							Andocken rechts	$_GUI_DOCK_RIGHT
;							Andocken unten	$_GUI_DOCK_BOTTOM
;							Andocken links	$_GUI_DOCK_LEFT
;							Andocken oben	$_GUI_DOCK_TOP
;
;							Ausrichten links oder oben		$_GUI_ALIGN_LEFTorTOP
;							Ausrichten zentriert			$_GUI_ALIGN_CENTER
;							Ausrichten rechts oder unten	$_GUI_ALIGN_RIGHTorBOTTOM
; Author(s):       BugFix (bugfix@autoit.de)
;===============================================================================
Func _GUIDock_SetAlignment($hWnd, $iAlign=Default)
	If IsKeyword($iAlign) Then $iAlign = BitOR($_GUI_DOCK_RIGHT,$_GUI_ALIGN_LEFTorTOP)
	For $i = 1 To UBound($aGUIDocks) -2
		If $hWnd = $aGUIDocks[$i][0] Then
			$aGUIDocks[$i][1] = $iAlign
			ExitLoop
		EndIf
	Next
	__moved()
EndFunc
#endregion

#region - interne Funktionen
Func __WndProc($hWnd, $iMsg, $iwParam, $ilParam)
	Local $indexWnd
	For $i = 0 To UBound($aGUIDocks) -2
		If $hWnd = $aGUIDocks[$i][0] Then
			$indexWnd = $i
			ExitLoop
		EndIf
	Next
    If $iMsg <> $WM_MOVE Then Return _WinAPI_CallWindowProc($ahProcHook[$indexWnd], $hWnd, $iMsg, $iwParam, $ilParam)
	__ArrangeGUI($indexWnd)
    Return _WinAPI_CallWindowProc($ahProcHook[$indexWnd], $hWnd, $iMsg, $iwParam, $ilParam)
EndFunc   ;==>__WndProc

Func __GUIDock_ShutDown()
	For $i = 0 To UBound($aGUIDocks) -2
		For $j = 0 To UBound($ahProcHook) -1
			_WinAPI_SetWindowLong($aGUIDocks[$i][0], $GWL_WNDPROC, $ahProcHook[$j])
		Next
	Next
EndFunc  ;==>__GUIDock_ShutDown

Func __ArrangeGUI($Index_Master=0)
	Local $iDiff, $aPos1, $aPos2
	If $aGUIDocks[UBound($aGUIDocks)-1][0] = -1 Then
		$iDiff = $iDockDistance
	Else
		$iDiff = $aGUIDocks[UBound($aGUIDocks)-1][0]
	EndIf
	If $Index_Master = 0 Then ; === Main-GUI bewegt
;~ 		$aPos1 = WinGetPos(WinGetHandle($aGUIDocks[0][0]))
		$aPos1 = WinGetPos($aGUIDocks[0][0])
		For $i = 1 To UBound($aGUIDocks) -2
			$aPos2 = WinGetPos(WinGetHandle($aGUIDocks[$i][0]))
			Select
				Case BitAND($aGUIDocks[$i][1], $_GUI_DOCK_RIGHT)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1])
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1]+($aPos1[3]-$aPos2[3])/2)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1]+$aPos1[3]-$aPos2[3])
				Case BitAND($aGUIDocks[$i][1], $_GUI_DOCK_BOTTOM)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0], $aPos1[1]+$aPos1[3]+$iDiff)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]+($aPos1[2]-$aPos2[2])/2, $aPos1[1]+$aPos1[3]+$iDiff)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]+$aPos1[2]-$aPos2[2], $aPos1[1]+$aPos1[3]+$iDiff)
				Case BitAND($aGUIDocks[$i][1], $_GUI_DOCK_LEFT)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1])
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1]+($aPos1[3]-$aPos2[3])/2)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1]+$aPos1[3]-$aPos2[3])
				Case BitAND($aGUIDocks[$i][1], $_GUI_DOCK_TOP)
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0], $aPos1[1]-$iDiff-$aPos2[3])
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]+($aPos1[2]-$aPos2[2])/2, $aPos1[1]-$iDiff-$aPos2[3])
					If BitAND($aGUIDocks[$i][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[$i][0], '', $aPos1[0]+$aPos1[2]-$aPos2[2], $aPos1[1]-$iDiff-$aPos2[3])
			EndSelect
		Next
	Else ; === Child bewegt ==> zuerst Main-GUI nachrücken
		$aPos1 = WinGetPos(WinGetHandle($aGUIDocks[$Index_Master][0]))
;~ 		$aPos2 = WinGetPos(WinGetHandle($aGUIDocks[0][0]))
		$aPos2 = WinGetPos($aGUIDocks[0][0])
		Select
			Case BitAND($aGUIDocks[$Index_Master][1], $_GUI_DOCK_LEFT)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1])
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1]+($aPos1[3]-$aPos2[3])/2)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1]+$aPos1[3]-$aPos2[3])
			Case BitAND($aGUIDocks[$Index_Master][1], $_GUI_DOCK_TOP)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[0][0], '', $aPos1[0], $aPos1[1]+$aPos1[3]+$iDiff)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]+($aPos1[2]-$aPos2[2])/2, $aPos1[1]+$aPos1[3]+$iDiff)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]+$aPos1[2]-$aPos2[2], $aPos1[1]+$aPos1[3]+$iDiff)
			Case BitAND($aGUIDocks[$Index_Master][1], $_GUI_DOCK_RIGHT)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1])
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1]+($aPos1[3]-$aPos2[3])/2)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1]+$aPos1[3]-$aPos2[3])
			Case BitAND($aGUIDocks[$Index_Master][1], $_GUI_DOCK_BOTTOM)
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_LEFTorTOP) Then WinMove($aGUIDocks[0][0], '', $aPos1[0], $aPos1[1]-$iDiff-$aPos2[3])
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_CENTER) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]+($aPos1[2]-$aPos2[2])/2, $aPos1[1]-$iDiff-$aPos2[3])
				If BitAND($aGUIDocks[$Index_Master][1], $_GUI_ALIGN_RIGHTorBOTTOM) Then WinMove($aGUIDocks[0][0], '', $aPos1[0]+$aPos1[2]-$aPos2[2], $aPos1[1]-$iDiff-$aPos2[3])
		EndSelect
		__moved() ; === $WM_MOVE senden um andere Childs auszurichten
	EndIf
EndFunc

Func __moved()
    DllCall("User32.dll", "int", "PostMessageA", "hwnd", $aGUIDocks[0][0], "int", $WM_MOVE, "int", 0, "int", 0)
EndFunc
#endregion

