- Offizieller Beitrag
Hi,
hier mal eine Lösung um Fenster aneinander zu docken. Nähere Erläuterungen im Skript.
Spoiler anzeigen
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
$gui1 = GUICreate("Nummer 1", 300, 300)
GUICtrlCreateGroup('Dockposition', 40, 40, 220, 220)
$r1 = GUICtrlCreateRadio('1', 240, 140, 15, 17)
GUICtrlSetState(-1, $GUI_CHECKED)
$r2 = GUICtrlCreateRadio('2', 140, 240, 15, 17)
$r3 = GUICtrlCreateRadio('3', 45, 140, 15, 17)
$r4 = GUICtrlCreateRadio('4', 140, 50, 15, 17)
GUICtrlCreateGroup('', -99, -99, 1, 1)
$gui2 = GUICreate("Ich bin gedockt", 200, 200)
Global $aDocks[2][4] = [[$gui1,$gui2,1,-1],[$gui2,$gui1,3,-1]]
; ['GUI-master','GUI-slave',dockPos,Abstand]
; dockPos: 1=rechts, 2=unten, 3=links, 4=oben
; Abstand: -1=SysMetrics Fensterrand, alle anderen Werte Pixelabstand zw. Fenstern
;=======================================================================================================
; Damit zwei Fenster wechselseitig reagieren, müssen beide im Array aufgeführt werden, einmal als Master
; und einmal als Slave.
; Dabei müssen die entgegengesetzten Flags für die Dockposition vergeben werden (1 u. 3 bzw. 2 u. 4)
;=======================================================================================================
GUISetState(@SW_SHOW, $gui2)
GUISetState(@SW_SHOW, $gui1)
; WM_MOVE registrieren:
GUIRegisterMsg($WM_MOVE, "WM_MOVE")
; Ereignis WM_MOVE auslösen zum erstmaligen Positionieren der Fenster
_moved()
While True
$msg = GUIGetMsg()
Switch $msg
Case -3
Exit
Case $r1
$aDocks[0][2] = 1
$aDocks[1][2] = 3
_moved()
Case $r2
$aDocks[0][2] = 2
$aDocks[1][2] = 4
_moved()
Case $r3
$aDocks[0][2] = 3
$aDocks[1][2] = 1
_moved()
Case $r4
$aDocks[0][2] = 4
$aDocks[1][2] = 2
_moved()
EndSwitch
WEnd
Func _moved()
DllCall("User32.dll", "int", "PostMessageA", "hwnd", WinGetHandle($aDocks[0][0]), "int", $WM_MOVE, "int", 0, "int", 0)
EndFunc
Func WM_MOVE($hWndGUI)
For $i = 0 To UBound($aDocks) -1
If WinGetHandle($aDocks[$i][0]) = $hWndGUI Then
Local $aPos1 = WinGetPos($aDocks[$i][0])
Local $aPos2 = WinGetPos($aDocks[$i][1]), $iDiff = 0
If $aDocks[$i][3] = -1 Then
Local $ret = DllCall("user32.dll", "int", "GetSystemMetrics", "int", 32)
If IsArray($ret) Then $iDiff = $ret[0]
Else
$iDiff = $aDocks[$i][3]
EndIf
Switch $aDocks[$i][2]
Case 1
WinMove($aDocks[$i][1], '', $aPos1[0]+$aPos1[2]+$iDiff, $aPos1[1])
Case 2
WinMove($aDocks[$i][1], '', $aPos1[0], $aPos1[1]+$aPos1[3]+$iDiff)
Case 3
WinMove($aDocks[$i][1], '', $aPos1[0]-$iDiff-$aPos2[2], $aPos1[1])
Case 4
WinMove($aDocks[$i][1], '', $aPos1[0], $aPos1[1]-$iDiff-$aPos2[3])
EndSwitch
EndIf
Next
Return $GUI_RUNDEFMSG
EndFunc
Edit 26.05.2009
Hier mal noch ein Beispiel zum Andocken eines Fensters an den Bildschirmrand.
Einstellbar ist der Fangbereich, indem das Fenster "gecatcht" wird und der Abstand der Fensterränder zum Desktoprand.
Spoiler anzeigen
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
Global $CatchWidth = 70 ; Pixelbereich indem das Fenster gefangen wird
Global $BorderDiff = 2 ; Pixelabstand zum Rand
Global $gui = GUICreate("Dock on Border", 300, 300)
GUISetState(@SW_SHOW, $gui)
; WM_MOVE registrieren:
GUIRegisterMsg($WM_MOVE, "WM_MOVE")
While True
$msg = GUIGetMsg()
Switch $msg
Case -3
Exit
EndSwitch
WEnd
Func WM_MOVE($hWndGUI)
If Not(WinGetHandle($gui) = $hWndGUI) Then Return $GUI_RUNDEFMSG
Local $aPos = WinGetPos($gui)
Local $Catch_Left = $CatchWidth, $Catch_Right = @DesktopWidth - $CatchWidth
Local $Catch_Top = $CatchWidth, $Catch_Bottom = @DesktopHeight - $CatchWidth
Select
Case $aPos[0] <= $Catch_Left
If $aPos[1] <= $Catch_Top Then
WinMove($gui, '', $BorderDiff, $BorderDiff)
ElseIf $aPos[1] + $aPos[3] >= $Catch_Bottom Then
WinMove($gui, '', $BorderDiff, @DesktopHeight - $BorderDiff - $aPos[3])
Else
WinMove($gui, '', $BorderDiff, $aPos[1])
EndIf
Case $aPos[0] + $aPos[2] >= $Catch_Right
If $aPos[1] <= $Catch_Top Then
WinMove($gui, '', @DesktopWidth - $BorderDiff - $aPos[2], $BorderDiff)
ElseIf $aPos[1] + $aPos[3] >= $Catch_Bottom Then
WinMove($gui, '', @DesktopWidth - $BorderDiff - $aPos[2], @DesktopHeight - $BorderDiff - $aPos[3])
Else
WinMove($gui, '', @DesktopWidth - $BorderDiff - $aPos[2], $aPos[1])
EndIf
Case $aPos[1] <= $Catch_Top
If $aPos[0] <= $Catch_Left Then
WinMove($gui, '', $BorderDiff, $BorderDiff)
ElseIf $aPos[0] + $aPos[2] >= $Catch_Right Then
WinMove($gui, '', @DesktopWidth - $BorderDiff - $aPos[2], $BorderDiff)
Else
WinMove($gui, '', $aPos[0], $BorderDiff)
EndIf
Case $aPos[1] + $aPos[3] >= $Catch_Bottom
If $aPos[0] <= $Catch_Left Then
WinMove($gui, '', $BorderDiff, @DesktopHeight - $BorderDiff - $aPos[3])
ElseIf $aPos[0] + $aPos[2] >= $Catch_Right Then
WinMove($gui, '', @DesktopWidth - $BorderDiff - $aPos[2], @DesktopHeight - $BorderDiff - $aPos[3])
Else
WinMove($gui, '', $aPos[0], @DesktopHeight - $BorderDiff - $aPos[3])
EndIf
EndSelect
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_MOVE
Edit 14.10.2010
Und hier mal noch ein Bsp. um mehrere Childs an eine Main-GUI zu kletten.
Spoiler anzeigen
#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 entgegengesetzt 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