; Demo für Sliden von Fenstern (sanftes hinein- oder hinausgleiten) von Fenstern aus dem Bereich des Bildschirms
; Es bleibt ein kleiner Fensterrand zu sehen - wird die Maus wieder über diesen bewegt, schiebt sich das
; Fenster wieder in den Bildschirm - wo es bleibt bis die Maus wieder ausserhalb des Fensters bewegt wird.
; 11/2011 von BLinz nach dem mich SEuBo von autoit.de auf die Idee gebracht hat,
; Original Beitrag: http://www.autoit.de/index.php?page=Thread&postID=238836&highlight=slide+gui#post238836
; Meine Lösung arbeitet ohne DLL aufrufe, "simpler" und besser kommentiert *g*

;Das Fenster mit Auswahl wohin ge-slided werden soll,
;Immer noch gerne mit dem Koda erstellt (sind ja nur ein paar Label und Buttons)
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=C:\_AutoIT\Z-Slider\FormMainWindow.kxf
$FormMainWindow = GUICreate("Z-Slider-DemoTest", 403, 331, 691, 240)
$LabelWhereIsTheMouse = GUICtrlCreateLabel("Maus ist ausserhalb des Fensters", 8, 88, 384, 25, BitOR($SS_CENTER,$SS_CENTERIMAGE,$WS_BORDER))
GUICtrlSetFont(-1, 12, 800, 0, "Courier New")
GUICtrlSetColor(-1, 0xFF0000)
$GroupGlobal = GUICtrlCreateGroup(" Globale Abfrage ", 8, 8, 384, 72)
$LabelMouseXLabel = GUICtrlCreateLabel("MouseX:", 16, 28, 60, 20)
GUICtrlSetFont(-1, 10, 800, 0, "Courier New")
$LabelMouseYLabel = GUICtrlCreateLabel("MouseY:", 16, 54, 60, 20)
GUICtrlSetFont(-1, 10, 800, 0, "Courier New")
$LabelMouseX = GUICtrlCreateLabel("0", 90, 30, 66, 17)
GUICtrlSetFont(-1, 10, 400, 0, "Courier New")
$LabelMouseY = GUICtrlCreateLabel("0", 90, 56, 66, 17)
GUICtrlSetFont(-1, 10, 400, 0, "Courier New")
GUICtrlCreateGroup("", -99, -99, 1, 1)
$GroupPosSlideWindow = GUICtrlCreateGroup(" Position Slide-Fenster ", 8, 120, 385, 201)
$ButtonTop = GUICtrlCreateButton("Oben", 160, 144, 100, 25)
$ButtonBottom = GUICtrlCreateButton("Unten", 160, 280, 100, 25)
$ButtonLeft = GUICtrlCreateButton("Links", 96, 174, 60, 100)
$ButtonRight = GUICtrlCreateButton("Rechts", 264, 174, 60, 100)
$LabelScreen = GUICtrlCreateLabel("Label1", 160, 174, 100, 100, BitOR($SS_WHITERECT,$WS_BORDER))
GUICtrlCreateGroup("", -99, -99, 1, 1)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###


; Ersteinmal die Grundeinstellungen ....
Global $nMsg ; Hier landet die Benachrichtigung von GUIGetMsg() - ob und welcher Button gedrückt wurde
Global $bWindowsIsOut = False ;Ob das Fenster gerade aus-ge-slidet ist (ja oder nein)
Global $sWindowsIsAt = "Left" ;Wohin wir das Fenster aus dem Bildschirm schieben
Global $iRealyBottom ; Sicherheitsabfrage falls der Benutzer das Fenster unten haben will

WinSetOnTop($FormMainWindow,"",1) ;Fenster immer ganz oben über allen anderen
GUICtrlSetState($ButtonLeft, $GUI_DISABLE) ; Die Demo startet immer mit links, also den Button ausgrauen

; Los geht es - die Hauptschleife
While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			; Jemand hat auf das rote X oben rechts geklickt
			Exit 0
		Case $ButtonLeft
			;Fenster soll nach Links sliden
			$sWindowsIsAt = "Left" ; Neue Richtung setzen
			GUICtrlSetState($ButtonLeft, $GUI_DISABLE) ; Button ausgrauen / deaktivieren
			GUICtrlSetState($ButtonRight, $GUI_ENABLE) ; Button aktivieren
			GUICtrlSetState($ButtonTop, $GUI_ENABLE) ; Button aktivieren
			GUICtrlSetState($ButtonBottom, $GUI_ENABLE) ; Button aktivieren
		Case $ButtonRight
			; nach Rechts, sonst sinngemäß wie zuvor
			$sWindowsIsAt = "Right"
			GUICtrlSetState($ButtonLeft, $GUI_ENABLE)
			GUICtrlSetState($ButtonRight, $GUI_DISABLE)
			GUICtrlSetState($ButtonTop, $GUI_ENABLE)
			GUICtrlSetState($ButtonBottom, $GUI_ENABLE)
		Case $ButtonTop
			; nach Oben, sonst sinngemäß wie zuvor
			$sWindowsIsAt = "Top"
			GUICtrlSetState($ButtonLeft, $GUI_ENABLE)
			GUICtrlSetState($ButtonRight, $GUI_ENABLE)
			GUICtrlSetState($ButtonTop, $GUI_DISABLE)
			GUICtrlSetState($ButtonBottom, $GUI_ENABLE)
		Case $ButtonBottom
			; nach Unten, sonst sinngemäß wie zuvor - jedoch mit Sicherheitsabfrage
			; Sicherheitsabfrage da bei meiner Monitoranordnung (3 Stück) das Fenster im Nirvana verschwindet
			$iRealyBottom = MsgBox(1,"Fenster unten plazieren","Wollen Sie das Fenster wirklich unten plazieren?" & @CRLF & _
								"Ja nach Anzahl und Anordnung der Monitore kann das Fenster dabei in den nicht" & @CRLF & _
								"Bereich landen - bzw. hinter der Taskleiste unerreichbar") ; 1 = OK und Abbrechen Button anzeigen
			If $iRealyBottom = 1 Then ; 1 = Ok Button wurde gedrückt (Abbrechen wäre 2)
				$sWindowsIsAt = "Bottom"
				GUICtrlSetState($ButtonLeft, $GUI_ENABLE)
				GUICtrlSetState($ButtonRight, $GUI_ENABLE)
				GUICtrlSetState($ButtonTop, $GUI_ENABLE)
				GUICtrlSetState($ButtonBottom, $GUI_DISABLE)
			EndIf
	EndSwitch
	; Ende der GUI-Auswertung (ob der Benutzer etwas geklickt hat)
	; Alles was jetzt kommt wird ständig ausgeführt

	;Aktuelle Mausposition in die GUI schreiben (nur als Info)
	$aMousePosCurrent = MouseGetPos(); MouseGetPos gibt ein Array zurück,[0] = X, [1] = Y Position der Maus
	GUICtrlSetData($LabelMouseX,$aMousePosCurrent[0])
	GUICtrlSetData($LabelMouseY,$aMousePosCurrent[1])

	; Schauen wir mal ob die Maus über dem Fenster ist
	If _Is_Mouse_in_Windows($FormMainWindow) = 1 Then ; siehe _Is_Mouse_in_Windows Funktion, 1 heisst ja
		GUICtrlSetData($LabelWhereIsTheMouse,"Maus ist im Fenster!") ; Text in GUI ändern
		GUICtrlSetColor($LabelWhereIsTheMouse, 0x00FF00) ; Text grün färben
		If $bWindowsIsOut = True Then ; Fenster nur ein-sliden wenn es auch draussen war
			_SlideWindow($FormMainWindow,$sWindowsIsAt,"In") ; Das eigentich Sliden, siehe Funktion _SlideWindow
			$bWindowsIsOut = False ; Fenster ist nun nicht draussen!
		EndIf
	Else ; Maus ist nicht über den Fenster
		GUICtrlSetData($LabelWhereIsTheMouse,"Maus ist ausserhalb des Fensters") ; Text ändern
		GUICtrlSetColor($LabelWhereIsTheMouse, 0xFF0000); Text rot färben
		If $bWindowsIsOut = False Then ; Fenster nur aus-sliden wenn es auch drin war
			_SlideWindow($FormMainWindow,$sWindowsIsAt,"Out")
			$bWindowsIsOut = True ; Fenster ist nun draussen!
		EndIf
	EndIf
WEnd

; #FUNCTION# ====================================================================================================================
; Name ..........: _SlideWindow
; Description ...:
; Syntax ........: _SlideWindow(Byref $hWitchWindow, $sWitchSide, $sInOrOut[, $iWindowBorderSize = 4[, $iSlideSteps = 4[,$iTimebetweenSlideSteps = 100]]])
; Parameters ....: $hWitchWindow        - A handle to the Target-Window
;                  $sWitchSide          - Where the Window should be slide? Possible Values are
;                                         "Left", "Right", "Top", "Bottom"
;                  $sInOrOut            - Slide window in or out? Possible Values are
;                                         "In", "Out"
;                  $iWindowBorderSize   - [optional] Size of Window Border (How many Pixel you will see if slided in)
;                  $iSlideSteps         - [optional] slide "animation"  in how many Steps? Default is 4.
;                  $iTimebetweenSlideSteps- [optional] Time in ms between the the steps, default is 100
; Return values .: None
; Author ........: BLinz
; Link ..........: http://znil.net
; Example .......: No
; ===============================================================================================================================
Func _SlideWindow(ByRef $hWitchWindow, $sWitchSide, $sInOrOut, $iWindowBorderSize = 4, $iSlideSteps = 4, $iTimebetweenSlideSteps = 100)
	Local $aScreenSize, $aWindowsSizeCurrent
	Local $iFrom, $iTo, $iSteps
	$aScreenSize = WinGetPos("Program Manager") ; In $aScreenSize steht nun die Größe der Desktopfläche
	                                            ; (hätte auch @DesktopHeight und @DesktopWidth nehmen können)
	$aWindowSizePosCurrent = WinGetPos($hwitchWindow) ;und hier holen wir uns die Größe und Position des Fensters
	Switch $sWitchSide ; Wohin soll das Fenster ?
		Case "Left" ; Aha, linke Seite
			$iMovePixelperStep = Round($aWindowSizePosCurrent[2] / $iSlideSteps,0) ; mal eben die Schrittweite in Pixel für die "Animation" berechnen
			For $i = $iSlideSteps To 0 Step -1 ; Anzahl der Schritte auf 0 herunterzählen - ja hier ist ein "Fehler" - er macht
											   ; Immer einen Schritt mehr als angegeben - aber der letzte ist 0 und damit Endposition
				If $sInOrOut = "Out" Then ; Ok, Fenster hinaus schubsen
					WinMove($hwitchWindow,"", 0 - ($aWindowSizePosCurrent[2] - ($iMovePixelperStep * $i)) + $iWindowBorderSize,$aWindowSizePosCurrent[1])
					; $aWindowSizePosCurrent[1] = Y-Position, bleibt unverändert
					; $aWindowSizePosCurrent[2] = Breite
					; ganz Links ist 0, davon ziehen wir pro Animationsschritt $i mal die Schrittweite ab. Ist i$ = 0 haben wir Endposition
					; Dazu die Breite des Randes damit dieser Sichtbar bleibt
				Else ;Fenster wieder reinholen
					WinMove($hwitchWindow,"", 0 + ($iWindowBorderSize - ($iMovePixelperStep * $i)),$aWindowSizePosCurrent[1])
					;wie zuvor, jedoch + statt -, wegen der zusätzlichen BorderSize kommt das Fenster ganz heraus
				EndIf
				Sleep($iTimebetweenSlideSteps)
			Next
		Case "Right"
			$iMovePixelperStep = Round($aWindowSizePosCurrent[2] / $iSlideSteps,0)
			For $i = $iSlideSteps To 0 Step -1
				If $sInOrOut = "Out" Then
					WinMove($hwitchWindow,"", $aScreenSize[2] - ($iMovePixelperStep * $i),$aWindowSizePosCurrent[1])
				Else
					WinMove($hwitchWindow,"", $aScreenSize[2] - ($aWindowSizePosCurrent[2] - ($iMovePixelperStep * $i)) - $iWindowBorderSize,$aWindowSizePosCurrent[1])
				EndIf
				Sleep($iTimebetweenSlideSteps)
			Next
		Case "Top"
			$iMovePixelperStep = Round($aWindowSizePosCurrent[2] / $iSlideSteps,0)
			For $i = $iSlideSteps To 0 Step -1
				If $sInOrOut = "Out" Then
					WinMove($hwitchWindow,"", $aWindowSizePosCurrent[0], 0 - ($aWindowSizePosCurrent[3] - ($iMovePixelperStep * $i)) + $iWindowBorderSize)
				Else
					WinMove($hwitchWindow,"", $aWindowSizePosCurrent[0], 0 + ($iWindowBorderSize - ($iMovePixelperStep * $i)))
				EndIf
				Sleep($iTimebetweenSlideSteps)
			Next
		Case "Bottom"
			$iMovePixelperStep = Round($aWindowSizePosCurrent[2] / $iSlideSteps,0)
			For $i = $iSlideSteps To 0 Step -1
				If $sInOrOut = "Out" Then
					WinMove($hwitchWindow,"", $aWindowSizePosCurrent[0], $aScreenSize[3] - ($iMovePixelperStep * $i))
				Else
					WinMove($hwitchWindow,"", $aWindowSizePosCurrent[0], $aScreenSize[3] - ($aWindowSizePosCurrent[3] - ($iMovePixelperStep * $i)) - $iWindowBorderSize)
				EndIf
				Sleep($iTimebetweenSlideSteps)
			Next
	EndSwitch
EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _Is_Mouse_in_Windows
; Description ...:
; Syntax ........: _Is_Mouse_in_Windows(Byref $hwitchWindow[, $iWindowBorderSize = 4])
; Parameters ....: $hwitchWindow        - A handle to the Target-Window
;                  $iWindowBorderSize   - [optional] Size of the Border of Window in Pixel
; Return values .: 1 = Mouse is in the Window
;                  0 = Mouse ist NOT in the Windows
; Author ........: BLinz
; Link ..........: http://znil.net
; Example .......: No
; ===============================================================================================================================
Func _Is_Mouse_in_Windows(ByRef $hwitchWindow, $iWindowBorderSize = 4)
	Local $aMousePosCurrent, $aWindowPosCurrent
	$aMousePosCurrent = MouseGetPos()
	$aWindowPosCurrent = WinGetPos($hwitchWindow)
	; $aWindowPosCurrent[0] = X-Position
	; $aWindowPosCurrent[1] = Y-Position
	; $aWindowPosCurrent[2] = Breite
	; $aWindowPosCurrent[3] = Höhe
	; Die BorderSize berücksichtigen wir weil die nicht zu 100% den Fenstermaßen zählt, also kleiner Aufschlag
	;Rechts vom Fenster?
	If $aMousePosCurrent[0] > ($aWindowPosCurrent[0] + $aWindowPosCurrent[2] + $iWindowBorderSize) Then Return 0
	;Links vom Fenster?
	If $aMousePosCurrent[0] < ($aWindowPosCurrent[0] - $iWindowBorderSize) Then Return 0
	;Unterhalb des Fensters?
	If $aMousePosCurrent[1] > ($aWindowPosCurrent[1] + $aWindowPosCurrent[3] + $iWindowBorderSize) Then Return 0
	;Oberhalb des Fensters?
	If $aMousePosCurrent[1] < ($aWindowPosCurrent[1] - $iWindowBorderSize) Then Return 0
	; Nix hat gepasst, Maus ist über dem Fenster
	Return 1
EndFunc
