#include-once
#include <WinAPIGdi.au3>		; Benötigt für _WinAPI_EnumDisplayMonitors, _WinAPI_GetMousePos, _WinAPI_MonitorFromPoint und _WinAPI_GetPosFromRect
Opt("MustDeclareVars",1)

; Beispiel: Erzeuge ein beliebiges Fenster und verschiebe es ggf.
Run("notepad.exe")											; hier einfachheitshalber nur Notepad öffnen
; Option 1 - benutze Titel des Fensters für $WindowTitle
; Local $WindowTitle="Unbenannt - Editor"						; Titel des Fensters festlegen (dies ist der deutsche Titel des Windowsfensters von dem Editor Notepad.exe)

; Option 2 - Benutze Windows Handle für $WindowTitle
Sleep(1000)
Local $WindowTitle=	WinGetHandle("Unbenannt - Editor")			; Alternativ über Windows Handle - Sicherstellen das Handle auch jetzt schon esistiert
If @error Then
	MsgBox (48, "Fehler", "Es ist ein Fehler aufgetreten, beim Versuch das Windows Handle zu bestimmen.")
	Exit
EndIf

; Option 3 - Benutze Klasse für $WindowTitle
; Local $WindowTitle="[CLASS:Notepad]"							; oder über Klasse

; Verschiebe Fenster wenn notwendig
If MoveWindowsToActiveDisplay($WindowTitle)=1 then					; Im Zweifelsfall verschiebt die Routine, das zuletzt geöffnente Fenster mit dem angegebenen Titel und Text
   MsgBox (0,"Erfolg","Fenster auf aktivem Display", 5)		; Timeout für Erfolgsmeldung = 5 Sekunden
Else														; Ansonsten Fehlermeldung ohne Timeout
   MsgBox (48,"Fehler", "Fenster nicht verschoben"&@CRLF&"Errorcode = "&@error&@CRLF&@CRLf& _
						"   1 = Fenster existiert nicht" &@CRLF&"   2 = kein Display gefunden"&@CRLF& _
						"   3 = kein aktives Display gefunden" )
EndIf

; #FUNCTION# ====================================================================================================================
; Name ..........: MoveWindowsToActiveDisplay
; Description ...: Bewegt in einer 2 Bildschirmkonfiguration ein Fenster dessen Titel übergeben wird auf das aktive Display,
;                  also dort sich gerade die Maus befindet.
; Syntax ........: MoveWindowsToActiveDisplay($ParmWindowTitle[, $ParmWindowText = ""[, $ParmTimeOut [, $ParmActivateWindow]])
; Parameters ....: $ParmWindowTitle     - Der Titel, das Handle oder die Klasse des Fensters das verschoben werden soll
;                  $ParmWindowText      - Test in dem Fenster verschoben werden soll. Default ist ein leerer String.
;                  $ParmTimeOut         - Maimaler Timeout in Sekunden bei der Suche nach dem Fenster. Default ist 3 Sekunden
;                  $ParmActivateWindow  - Wenn Wert 1 dann aktiviere Fenster um es in den Vordergrund zu bringen.
;                                         Defaultwert ist 1
; Return values .: 1 - Funktion erfolgreich beendet
;                  0 - Ein Fehler ist aufgetreten
; Author ........: PapaPeter
; Modified ......: 4.5.2020 (mit Berücksichtigung von Bemerkungen von Bitnugger)
; Remarks .......: Errorcodes: 1 - Fenster existiert nicht
;                              2 - Kein Bildschirm erkannt
;                              3 - Aktiver Bildschirm konnte nicht bestimmt werden
;                  Tested mit AutoIt Version 3.3.14.2
;                  --------------------------------------------------------------------------------------------------------------
;                  Es gibt zwei Versionen dieser Datei. Diese Version ist mit debug Optionen in beiden Funktionen ausgestattet
;                  und mit deutschen Kommentaren teilweise ausführlicher dokumentiert.Es gibt auch eine UDF-Version dieser Datei
;                  mit englischen Kommentaren und verkürzter Hilfsfunktion CheckCoordinatesInRange.
;                  --------------------------------------------------------------------------------------------------------------
;                  Diese Version ist zur Zeit nur mit 2 Bildschirmen getestet worden, Tests mit 3 oder Mehr Bildschirmen können
;                  weitere Änderungen am Code bedingen.
; Related .......: Die Hilfsfunktion CheckCoordinatesInRange im selben Sourcecode wird verwendet
; Link ..........: https://autoit.de/thread/86942-autoit-script-f%C3%BCr-multi-bildschirm-betrieb/
; Example .......: MoveWindowsToActiveDisplay("Unbenannt - Editor")
; ===============================================================================================================================
Func MoveWindowsToActiveDisplay($ParmWindowTitle, $ParmWindowText="", $ParmTimeOut=5, $ParmActivateWindow=1)
	; Initialisierung
	Local $ReturnValue = 1													; Wenn kein Fehler auftritt ist $ReturnValue 1
	Local $Debug=1															; Debugvariable (0 = keine Debugging-Ausgaben auf Konsole, 1 = Debugging-Ausgaben auf Konsole)
	ConsoleWrite(@min&":"&@SEC&":"&@MSEC&@CRLF)
	If  $ParmActivateWindow=1 then											; Wenn Fenster aktiviert werden soll
		If $Debug=1 Then ConsoleWrite('... Warte auf Fenster $ParmActivateWindow' & @CRLF)
		WinActivate($ParmWindowTitle, $ParmWindowText)							; Benutzt die Kombination WinActivate/WinWaitActive um sicher zu stellenn das das Fenster schon existiert und sichtbar ist
		WinWaitActive($ParmWindowTitle, $ParmWindowText, $ParmTimeOut)			; Wartet maximal $ParmTimeOut Sekunden ob das Fenster aktiviert werden konnte
	Else																	; Wenn Fenster nicht aktiviert werden soll
		Local $Count=1															; Schleife die maximal $ParmTimeOut Sekunden darauf wartet, daß das Fenster existiert
		While ($Count<$ParmTimeOut And Not WinExists($ParmWindowTitle, $ParmWindowText))	; Prüfen ob maximale Zeit überschritten oder Fenster schon existiert
			Sleep(1000)
			$Count+=1
			If $Debug=1 Then ConsoleWrite('... Warte auf Fenster' & @CRLF)
		WEnd
	EndIf

	; Liest Koordinaten des übergebenen Fensters aus
	Local $WindowCoordinates=WinGetPos($ParmWindowTitle,$ParmWindowText)	; Koordinaten des Fenster in Array $WindowCoordinates einlesen

	; Bestimmt aktuell aktives Display(/Monitor) aus der aktueller Mausposition und Funktion _WinAPI_MonitorFromPoint
	Local $MousePos = _WinAPI_GetMousePos()									; Liest aktuelle Mausposition aus
	Local $ActualMonitorHandle = _WinAPI_MonitorFromPoint($MousePos)		; Bestimmt Displaymonitor Handle zur aktuellen Mausposition

	; Lese Infos zu den angeschlossenen Monitoren aus
	Local $DisplayData = _WinAPI_EnumDisplayMonitors()						; Gibt ein Array mit den Handles der vorhandenen Displaymonitore zurück

	If WinExists($ParmWindowTitle) Then										; Prüfen ob Fenster existiert -> Fenster existiert

		; Suche aktives Display und verschiebe Fenster wenn notwendig
		If IsArray($DisplayData) Then											; Wenn Displays erkannt wurden
			Local $NumDisplays=$DisplayData[0][0]									; Bestimme Anzahl der Displays aus ersten Wert des Rückgabearrays von _WinAPI_EnumDisplayMonitors
			Local $ActiveDisplay=0													; Defaultwert für aktives Display festlegen (0 ist primäres Display)
			; Lese Parameter des aktiven Fensters aus
			For $DisplayCount = 1 To $NumDisplays									; Schleife über Daten aller Displays
				if $DisplayData[$DisplayCount][0]= $ActualMonitorHandle Then					; Vergleiche mit Handle des aktiven Displays
					Local $ActiveDisplayData = _WinAPI_GetPosFromRect($DisplayData[$DisplayCount][1])	; wenn gleich Daten dann in Array $ActiveDisplayData einlesen
				EndIf
			Next
			If IsArray($ActiveDisplayData) Then										; Wenn aktives Display gefunden
				; Prüfen ob ein Verschieben des Fensters notwendig
				if Not CheckCoordinatesInRange($WindowCoordinates, $ActiveDisplayData)=1 Then ; Verschieben  notwendig
																								; Verschiebe Fenster wobei $ActiveDisplayData[0] der horizontale und
																								;    $ActiveDisplayData[1] vertikaler Offset ist (kann auch negativ sein)
					WinMove($ParmWindowTitle, $ParmWindowText, $WindowCoordinates[0]+ $ActiveDisplayData[0], $WindowCoordinates[1]+$ActiveDisplayData[1])
					If  $ParmActivateWindow=1 then												; Muß Fenster aktiviert werden?
						WinActivate($ParmWindowTitle,$ParmWindowText)								; Fenster aktivieren um es in den Vordergrund zu holen
					EndIf
					If $Debug=1 Then ConsoleWrite('Erfolg - Fenster verschoben' & @CRLF)
				EndIf
			Else																	; kein aktives Display gefunden
				SetError(3, 0, 0)														; Kein aktives Display erkannt
				$ReturnValue = 0														; also ReturnValue = 0 und Errorcode = 3
				If $Debug=1 Then ConsoleWrite('Error 3 = Kein aktives Display erkannt' & @CRLF)
			EndIf
		Else																	; Wenn kein Display erkannt wurde
			SetError(2, 0, 0)															; Kein Display erkannt
			$ReturnValue = 0															; also ReturnValue = 0 und Errorcode = 2
			If $Debug=1 Then ConsoleWrite('Error 2 = Kein Display erkannt' & @CRLF)
		EndIf
	Else																	; Fenster existiert nicht
		SetError(1, 0, 0)														; Fenster nicht gefunden
		$ReturnValue = 0														; also ReturnValue = 0 und Errorcode = 1
		If $Debug=1 Then ConsoleWrite('Error 1 = Fenster nicht gefunden' & @CRLF)
	EndIf

	Return $ReturnValue
EndFunc		; ==> MoveToActiveDisplay()

; #FUNCTION# ====================================================================================================================
; Name ..........: CheckCoordinatesInRange
; Description ...: Überprüft ob Koordinaten in $Parm_CheckCoordinatesArray in der Fläche liegen die $Parm_DisplayArray definiert
; Syntax ........: CheckCoordinatesInRange($Parm_CheckCoordinatesArray, $Parm_DisplayArray)
; Parameters ....: $Parm_CheckCoordinatesArray - Array mit miondestens 2 Einträgen für die X & Y Koordinaten.
;                  $Parm_DisplayArray - Flächen-Array mit mindestens 4 Einträgen für X, Y, Breite & Höhe.
;                  $Parm_CheckCoordinatesArray[0] = Wert der X-Koordinate die überprüft wird
;                  $Parm_CheckCoordinatesArray[1] = Wert der Y-Koordinate die überprüft wird
;                  $Parm_DisplayArray[0]          = Wert der X-Koordinate der linken oberen Ecke der Fläche
;                  $Parm_DisplayArray[1]          = Wert der Y-Koordinate der linken oberen Ecke der Fläche
;                  $Parm_DisplayArray[2]          = Wert der Breite der Fläche
;                  $Parm_DisplayArray[3]          = Wert der Höhe der Fläche
; Return values .: 1 - Koordinaten liegen in Fläche
;                  0 - Koordinaten liegen in Fläche
; Author ........: PapaPeter
; Modified ......: 4.5.2020 by PapaPeter
; Remarks .......: Errorcodes: 1 - $Parm_CheckCoordinatesArray ist kein Array
;                              2 - $Parm_DisplayArray ist kein Array
;                  Getestet unter AutoIt Version 3.3.14.2
;                  ---------------------------------------------------------------------------------------------------------------
;                  Dies ist leichter lesbare Variante der Funktion, eine analoge kürze Form von BugFix findet sich in der UDF
;                  Version dieser Datei. Funktionell sind die beiden Varianten gleichwertig. Diese Version ist vermutlich etwas
;                  langsamer.
; Related .......: Wird von MoveWindowsToActiveDisplay benutzt
; Link ..........: https://autoit.de/thread/86942-autoit-script-f%C3%BCr-multi-bildschirm-betrieb/
; Example .......: kein Beispiel vorhanden
; ===============================================================================================================================
Func CheckCoordinatesInRange($Parm_CheckCoordinatesArray, $Parm_DisplayArray)
   Local $ReturnValue=0								  ; Initialisierung ReturnValue
   Local $Debug=0									  ; Debugvariable (0 = keine Debugging-Ausgaben auf Konsole, 1 = Debugging-Ausgaben auf Konsole)
   If Not IsArray($Parm_CheckCoordinatesArray) Then   ; Überprüfe ob erster Parameter ein Array ist
	  If $Debug=1 Then ConsoleWrite('Error 1' & @CRLF)
	  SetError(1, 0, -1)
	  $ReturnValue=-1
   ElseIf Not IsArray($Parm_DisplayArray) Then		  ; Überprüfe ob zweiter Parameter ein Array ist
	  If $Debug=1 Then ConsoleWrite('Error 2' & @CRLF)
	  $ReturnValue=-1
    Else											  ; Ansonsten weitermachen mit den Übergabeparametern
	  If $Debug=1 Then ConsoleWrite('No Error' & @CRLF)
														 ; Überpüfe die X-Koordinate (0)
	  if  ($Parm_DisplayArray[0]<= $Parm_CheckCoordinatesArray[0]) And (($Parm_CheckCoordinatesArray[0] < $Parm_DisplayArray[0]+$Parm_DisplayArray[2])) Then
		 If $Debug=1 Then ConsoleWrite ("   X: "&$Parm_DisplayArray[0]&"<=" & $Parm_CheckCoordinatesArray[0] & "<" & $Parm_DisplayArray[0]+$Parm_DisplayArray[2] & "   -> X in Range"& @CRLF)
														 ; X-Koordinate liegt im Bereich der Fläche
														 ; Überpüfe die Y-Koordinate (1)
		 If ($Parm_DisplayArray[1]<= $Parm_CheckCoordinatesArray[1]) And ($Parm_CheckCoordinatesArray[1] < ($Parm_DisplayArray[1]+$Parm_DisplayArray[3])) Then
															   ; X-und Y-Koordinaten liegen im Bereich der Fläche
			If $Debug=1 Then ConsoleWrite ("   Y: "&$Parm_DisplayArray[1]&"<=" & $Parm_CheckCoordinatesArray[1] & "<" & $Parm_DisplayArray[1]+$Parm_DisplayArray[3] & "   -> Y in Range"& @CRLF)
			$ReturnValue=1
		 Else											 	   ; Y-Koordinate liegt nicht im Bereich der Fläche
			If $Debug=1 Then ConsoleWrite("Y-Coordinate not in Range: "& $Parm_CheckCoordinatesArray[1]&@crlf)
			$ReturnValue=0
		 EndIf
	  Else												 ; X-Koordinate liegt nicht im Bereich der Fläche
		 If $Debug=1 Then ConsoleWrite("X-Coordinate not in Range: "& $Parm_CheckCoordinatesArray[0]&@crlf)
		 $ReturnValue=0
	  EndIf
   EndIf
   Return $ReturnValue
EndFunc		; ==>  CheckCoordinatesInRange()