- Offizieller Beitrag
In Erweiterung meiner Bsp. hier, habe ich nun eine Funktionssammlung erstellt um GUI beliebig aneinander zu docken.
Die anzudockenden Fenster lassen sich rechts, unten, links oder oben platzieren und jeweils links-(bzw.oben)bündig, zentriert oder rechts-(bzw. unten)bündig ausrichten.
Es können jederzeit Fenster wieder abgedockt oder deren Ausrichtung geändert werden.
Funktionsübersicht
===== Funktionsübersicht =====
_GUIDock_StartUp($hWnd)
Initialisiert notwendige Variablen
$hWnd bekommt Status MainWindow
registrieren der 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
Alles anzeigen
GUIDocking.au3
#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 ([email='bugfix@autoit.de'][/email])
;===============================================================================
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 ([email='bugfix@autoit.de'][/email])
;===============================================================================
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 ([email='bugfix@autoit.de'][/email])
;===============================================================================
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 ([email='bugfix@autoit.de'][/email])
;===============================================================================
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 ([email='bugfix@autoit.de'][/email])
;===============================================================================
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
Beispiel
#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
#include 'GUIDocking.au3'
#include <GUIConstantsEx.au3>
$gui1 = GUICreate("Nummer 1", 300, 300)
$btUndock = GUICtrlCreateButton('UnDock GUI UNTEN', 50, 50, 200, 20)
$btRedock = GUICtrlCreateButton('ReDock GUI UNTEN', 50, 90, 200, 20)
GUICtrlSetState(-1, $GUI_DISABLE)
$gui2 = GUICreate("Ich bin gedockt RECHTS-UNTEN", 200, 200, -1, -1, -1, $WS_EX_TOOLWINDOW)
$gui3 = GUICreate("Ich bin gedockt LINKS-OBEN", 200, 200, -1, -1, -1, $WS_EX_TOOLWINDOW)
$gui4 = GUICreate("Ich bin gedockt UNTEN-LINKS", 400, 200, -1, -1, -1, $WS_EX_TOOLWINDOW)
GUISetState(@SW_SHOW, $gui4)
GUISetState(@SW_SHOW, $gui3)
GUISetState(@SW_SHOW, $gui2)
GUISetState(@SW_SHOW, $gui1)
; === Docking starten mit Übergabe der Main-GUI
_GUIDock_StartUp($gui1)
; === Array mit zu dockenden GUI erstellen
Local $aGUI[3] = [$gui2,$gui3,$gui4]
; === Array mit Kombination Dockposition/-ausrichtung je GUI
Local $aAlign[3] = [BitOR($_GUI_DOCK_RIGHT,$_GUI_ALIGN_RIGHTorBOTTOM), _
BitOR($_GUI_DOCK_LEFT,$_GUI_ALIGN_LEFTorTOP), _
BitOR($_GUI_DOCK_BOTTOM,$_GUI_ALIGN_LEFTorTOP)]
; === Andocken der Fenster und gleichzeitiges Ausrichten
_GUIDock_DockWindow($aGUI, $aAlign)
; === oder erst nur GUI's docken und dann einzeln ausrichten:
;~ _GUIDock_DockWindow($aGUI)
;~ _GUIDock_SetAlignment($gui2, BitOR($_GUI_DOCK_RIGHT,$_GUI_ALIGN_RIGHTorBOTTOM))
;~ _GUIDock_SetAlignment($gui3, BitOR($_GUI_DOCK_LEFT,$_GUI_ALIGN_LEFTorTOP))
;~ _GUIDock_SetAlignment($gui4, BitOR($_GUI_DOCK_BOTTOM,$_GUI_ALIGN_LEFTorTOP))
While True
Switch GUIGetMsg()
Case -3
Exit
Case $btUndock
; === einzelnes Fenster UnDocken
_GUIDock_UnDockWindow($gui4)
WinSetTitle($gui4, '', "Ich bin UNgedockt.")
GUICtrlSetState($btUndock, $GUI_DISABLE)
GUICtrlSetState($btRedock, $GUI_ENABLE)
Case $btRedock
; === einzelnes Fenster Docken
_GUIDock_DockWindow($gui4, BitOR($_GUI_DOCK_BOTTOM,$_GUI_ALIGN_CENTER))
WinSetTitle($gui4, '', "Ich bin gedockt UNTEN-MITTE")
GUICtrlSetState($btUndock, $GUI_ENABLE)
GUICtrlSetState($btRedock, $GUI_DISABLE)
EndSwitch
WEnd
Falls die Frage kommt, warum solch großer Aufwand betrieben wird - das erreicht man doch auch mit Child-Windows?
Genau deshalb habe ich es gemacht, damit man auch Nicht-Child-Windows aneinander docken kann.
Und außerdem finde ich die Abdockmöglichkeit als nicht unwesentlich - und das bietet ein Child nicht.
Edit:
Habe die ShutDown-Funktion jetzt automatisch eingebunden. Danke Raupi für den Tipp.