In meinem Slider Projekt habe ich das Problem, das unsinnige Seiten für das Sliderfenster nicht erkannt werden.
Unsinnig ist z.B. die Position zwischen 2 Monitoren.
also habe ich mir etwas geschrieben was die Postionen erkennt und darstellen kann - DisplayMonitorConfiguration.au3
Features:
- Anzahl und Größe der Monitore erkennen und Maßstabsgerecht zeichnen
- Die freien Ränder der einzelnen Monitore ermitteln
- Die freien Ränder anzeigen (wieder im Maßstab)
- Die "Zeichnung" kann Platz in der GUI angepasst werden (Slider in Demo)
- Anzahl und Auflösung der Monitore ist "unbegrenzt"
Bilder aus der Praxis
Meine Bildschirmanordnung:
[Blockierte Grafik: http://znil.net/images/e/e9/DisplayMonitor001.JPG]
Durch das Skript erkannte Darstellung:
[Blockierte Grafik: http://znil.net/images/5/5d/DisplayMonitor002.JPG]
Durch das Skript erkannte freien Ränder (Mit Darstellung meiner Monitore):
[Blockierte Grafik: http://znil.net/images/7/70/DisplayMonitor003.JPG]
Gegenprobe: Monitor 1 und 2+3 vertauscht, 2 und 3 liegen nun auf negativen Koordninaten
[Blockierte Grafik: http://znil.net/images/8/87/DisplayMonitor004.JPG]
Und was das Skript daraus macht:
[Blockierte Grafik: http://znil.net/images/e/ed/DisplayMonitor005.JPG]
Hier der Quellcode:
Spoiler anzeigen
; 12 / 2011 von BLinz - http://www.autoit.de
#include <Array.au3>
#include <GUIConstantsEx.au3>
#include <SliderConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
Global $aScreenDimension ; Hier kommen die Gesamtmaße (Gesamtbreite / Höhe) der Monitore rein zwecks Maßstabsbrechnung
Global $aAllScreenswithDimensions ; Hier stehen Anzahl, Position und Maße aller Monitore drin
Global $iResizeFaktor ; Um welchen Faktor müssen wir verkleinern beim Zeichnen
Global $iZeroPointX, $iZeroPointY ; Wohin mit dem Nullpunkt auf unserer Zeichenfläche (wegen Negativen Koordinaten)
Global $LabelMonitors[1] ; Zeiger auf die Label die die Monitore darstellen
Global $aUseableMonitorMargins[1][4] ; Hier kommt für jede der 4 Seiten eine Monitors ein Wert rein
; ob diese Frei ist (True) oder an einen anderen angrenzt (False)
Global $ButtonMargins[1] ; Die Ränder werden mit Buttons dargestellt, hier die Zeiger dafür
Global $iDrawingSize = 300 ; Grundwert, Größe der Zeichenfläche, kann per Slider angepasst werden
Global $iOldSliderValue ; Für Echtzeitvorschau wenn der Slider bewegt wird
Global $bShowMargins = False ; Grundwert, nicht die Ränder zeigen an denen ein Slider Fenster hin könnte
;Wieder kleine GUI mit Koda ...
#Region ### START Koda GUI section ### Form=c:\_autoit\z-slider\displaymonitorconfiguration.kxf
$FormDisplayMonitorConfiguration = GUICreate("DisplayMonitorConfigurationDEMO", 615, 601, 409, 137)
$Slider1 = GUICtrlCreateSlider(56, 496, 500, 45, BitOR($GUI_SS_DEFAULT_SLIDER,$TBS_TOP,$TBS_LEFT,$TBS_ENABLESELRANGE))
$Label1 = GUICtrlCreateLabel("100px", 56, 480, 33, 17)
$Label2 = GUICtrlCreateLabel("600px", 528, 480, 33, 17)
$CheckboxShowPossibleSlider = GUICtrlCreateCheckbox("Zeige mögliche Positionen für ein Slider Fenster", 64, 544, 481, 17)
$ButtonMonArray = GUICtrlCreateButton("Zeige Monitore-Array", 64, 568, 130, 25)
$ButtonMarginArray = GUICtrlCreateButton("Zeige freie Seiten Array", 336, 568, 130, 25)
$ButtonScreenDims = GUICtrlCreateButton("Zeige BildschirmDims", 200, 568, 130, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
;Slider auf Startwert setzen
GUICtrlSetData($Slider1, ($iDrawingSize - 100) / 5)
$iOldSliderValue = GUICtrlRead($Slider1)
;Gesamte Bildschrimausmaße über alle Monitore ermitteln,
; Ergibt auch bei Monitoren mit negativen Koordinaten die Gesamtbreite / -höhe
$aScreenDimension = WinGetPos("Program Manager")
;$aScreenDimension[0] = X-Position
;$aScreenDimension[1] = Y-Position
;$aScreenDimension[2] = Breite
;$aScreenDimension[3] = Höhe
;_ArrayDisplay($aScreenDimension)
[/autoit] [autoit][/autoit] [autoit];Umrechnungsfaktor für unsere (momentan 300 x 300) Fläche ermitteln
If $aScreenDimension[2] > $aScreenDimension[3] Then
$iResizeFaktor = $iDrawingSize / $aScreenDimension[2]
Else
$iResizeFaktor = $iDrawingSize / $aScreenDimension[3] ;
EndIf
;Nullpunkte für unsere (momentan noch 300 x 300) Fläche ermitteln
; 0 = 300 - 300 / ( 3600 / ( 0 + 3600))
; 140 = 300 - 300 / ( 3600 / ( -1680 + 3600))
$iZeroPointX = $iDrawingSize - ($iDrawingSize / ($aScreenDimension[2] / ($aScreenDimension[0] + $aScreenDimension[2])))
;Nun kann es sein das ein negativer Wert herauskommt - dann in positiv wandeln
If $iZeroPointX < 0 Then $iZeroPointX = $iZeroPointX * (-1)
;Das selbe noch einmal für Y Achse
$iZeroPointY = $iDrawingSize - ($iDrawingSize / ($aScreenDimension[3] / ($aScreenDimension[1] + $aScreenDimension[3])))
If $iZeroPointY < 0 Then $iZeroPointX = $iZeroPointY * (-1)
; Anzahl und Auflösung der einzelnen Monitore holen
$aAllScreenswithDimensions = _GetMonitors()
; $aAllScreenswithDimensions[0][0] with number of Monitors,
; $aAllScreenswithDimensions[x][0] Monitor X Screen wide
; $aAllScreenswithDimensions[x][1] Monitor X Screen height
; $aAllScreenswithDimensions[x][2] Monitor X Screen Position X
; $aAllScreenswithDimensions[x][3] Monitor X Screen Position Y
; Ermitteln an welchen Rändern die Monitore "zusammenstoßen" bzw. verbunden sind
Redim $aUseableMonitorMargins[$aAllScreenswithDimensions[0][0] + 1][4]
$aUseableMonitorMargins[0][0] = "Links"
$aUseableMonitorMargins[0][1] = "Rechts"
$aUseableMonitorMargins[0][2] = "Oben"
$aUseableMonitorMargins[0][3] = "Unten"
; $aUseableMonitorMargins[x][0] = Left Margin
; $aUseableMonitorMargins[x][1] = Right Margin
; $aUseableMonitorMargins[x][2] = Top Margin
; $aUseableMonitorMargins[x][3] = Bottom Margin
; Ermittel welcher Monitor wo steht und an welchen Seiten diese aneinander stoßen
_GetMonitorMargins()
;Die Monitore stellen wir durch Labels dar - Anzahl dimensonieren
ReDim $LabelMonitors[$aAllScreenswithDimensions[0][0] + 1]
$LabelMonitors[0] = $aAllScreenswithDimensions[0][0]
;Die freien Ränder durch Buttons - einfach Monitore * 4 - sind zwar bestimmt zuviel aber nie zuwenig
Redim $ButtonMargins[$aAllScreenswithDimensions[0][0] * 4]
;Monitore zeichnen
_DrawMonitors()
;Hauptschleife zur Abfrage der GUI
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $CheckboxShowPossibleSlider
;Ok, jemand will die freien Seiten sehen (oder nicht mehr sehen)
If BitAnd(GUICtrlRead($CheckboxShowPossibleSlider),$GUI_CHECKED) = $GUI_CHECKED Then
$bShowMargins = True ; Anzeigen
Else
$bShowMargins = False ; Nicht anzeigen
EndIf
;Einmal alles neu Zeichnen lassen
_DeleteMonitors()
_DrawMonitors()
Case $ButtonMonArray
_ArrayDisplay($aAllScreenswithDimensions)
Case $ButtonMarginArray
_ArrayDisplay($aUseableMonitorMargins)
case $ButtonScreenDims
_ArrayDisplay($aScreenDimension)
EndSwitch
;Echtzeitvorschau des Sliders, neu zeichnen wenn der Wert sich ändert
If $iOldSliderValue <> GUICtrlRead($Slider1) Then
$iDrawingSize = (GUICtrlRead($Slider1) * 5) + 100 ;Slider ist von 0 bis 100, Werte aber von 100 bis 600
; Verkleinerungsfaktor neu ausrechnen
If $aScreenDimension[2] > $aScreenDimension[3] Then
$iResizeFaktor = $iDrawingSize / $aScreenDimension[2]
Else
$iResizeFaktor = $iDrawingSize / $aScreenDimension[3]
EndIf
$iOldSliderValue = GUICtrlRead($Slider1)
$iZeroPointX = $iDrawingSize - ($iDrawingSize / ($aScreenDimension[2] / ($aScreenDimension[0] + $aScreenDimension[2])))
If $iZeroPointX < 0 Then $iZeroPointX = $iZeroPointX * (-1)
$iZeroPointY = $iDrawingSize - ($iDrawingSize / ($aScreenDimension[3] / ($aScreenDimension[1] + $aScreenDimension[3])))
If $iZeroPointY < 0 Then $iZeroPointX = $iZeroPointY * (-1)
_DeleteMonitors()
_DrawMonitors()
EndIf
WEnd
;löscht alle gezeichten Labels und Buttons
Func _DeleteMonitors()
For $i = 1 To $LabelMonitors[0]
GUICtrlDelete($LabelMonitors[$i])
Next
For $i = 0 To UBound($ButtonMargins) - 1
GUICtrlDelete($ButtonMargins[$i])
Next
EndFunc
;Zeichnet die Monitore und ggf. Buttons Maßstabsgerecht
; $aAllScreenswithDimensions[0][0] with number of Monitors,
; $aAllScreenswithDimensions[x][0] Monitor X Screen wide
; $aAllScreenswithDimensions[x][1] Monitor X Screen height
; $aAllScreenswithDimensions[x][2] Monitor X Screen Position X
; $aAllScreenswithDimensions[x][3] Monitor X Screen Position Y
Func _DrawMonitors()
Local $j = 0
For $i = 1 To $LabelMonitors[0]
$LabelMonitors[$i] = GUICtrlCreateLabel($i, 16 + $iZeroPointX + Floor($aAllScreenswithDimensions[$i][2] * $iResizeFaktor), _
16 + $iZeroPointY + Floor($aAllScreenswithDimensions[$i][3] * $iResizeFaktor), _
Floor($aAllScreenswithDimensions[$i][0] * $iResizeFaktor), _
Floor($aAllScreenswithDimensions[$i][1] * $iResizeFaktor), _
BitOR($SS_CENTER,$SS_CENTERIMAGE,$WS_BORDER))
GUICtrlSetFont($LabelMonitors[$i], 14, 800, 0, "Courier New")
GUICtrlSetBkColor($LabelMonitors[$i], 0xffffff)
; $aUseableMonitorMargins[x][0] = Left Margin
; $aUseableMonitorMargins[x][1] = Right Margin
; $aUseableMonitorMargins[x][2] = Top Margin
; $aUseableMonitorMargins[x][3] = Bottom Margin
If $bShowMargins = True Then
; links Button setzen bei Bedarf
If $aUseableMonitorMargins[$i][0] = True Then
$ButtonMargins[$j] = GUICtrlCreateButton("", 16 + $iZeroPointX + Floor($aAllScreenswithDimensions[$i][2] * $iResizeFaktor), _
16 + $iZeroPointY + Floor($aAllScreenswithDimensions[$i][3] * $iResizeFaktor), _
12, _
Floor($aAllScreenswithDimensions[$i][1] * $iResizeFaktor))
GUICtrlSetBkColor($ButtonMargins[$j], 0x00ff00)
$j = $j + 1
EndIf
; rechts Button setzen bei Bedarf
If $aUseableMonitorMargins[$i][1] = True Then
$ButtonMargins[$j] = GUICtrlCreateButton("", 4 + $iZeroPointX + Floor(($aAllScreenswithDimensions[$i][2] + $aAllScreenswithDimensions[$i][0]) * $iResizeFaktor), _
16 + $iZeroPointY + Floor($aAllScreenswithDimensions[$i][3] * $iResizeFaktor), _
12, _
Floor($aAllScreenswithDimensions[$i][1] * $iResizeFaktor))
GUICtrlSetBkColor($ButtonMargins[$j], 0x00ff00)
$j = $j + 1
EndIf
; oben setzen bei Bedarf
If $aUseableMonitorMargins[$i][2] = True Then
$ButtonMargins[$j] = GUICtrlCreateButton("", 16 + $iZeroPointX + Floor($aAllScreenswithDimensions[$i][2] * $iResizeFaktor), _
16 + $iZeroPointY + Floor($aAllScreenswithDimensions[$i][3] * $iResizeFaktor), _
Floor($aAllScreenswithDimensions[$i][0] * $iResizeFaktor), _
12)
GUICtrlSetBkColor($ButtonMargins[$j], 0x00ff00)
$j = $j + 1
EndIf
; unten setzen bei Bedarf
If $aUseableMonitorMargins[$i][3] = True Then
$ButtonMargins[$j] = GUICtrlCreateButton("", 16 + $iZeroPointX + Floor($aAllScreenswithDimensions[$i][2] * $iResizeFaktor), _
4 + $iZeroPointY + Floor(($aAllScreenswithDimensions[$i][3] + $aAllScreenswithDimensions[$i][1]) * $iResizeFaktor), _
Floor($aAllScreenswithDimensions[$i][0] * $iResizeFaktor), _
12)
GUICtrlSetBkColor($ButtonMargins[$j], 0x00ff00)
$j = $j + 1
EndIf
EndIf
Next
EndFunc
;Findet heraus welcher Monitor mit welcher Seite an welchen anderen Monitor stößt
; True = Seite Frei
; False = Da ist ein anderer Monitor
; $aUseableMonitorMargins[x][0] = Left Margin
; $aUseableMonitorMargins[x][1] = Right Margin
; $aUseableMonitorMargins[x][2] = Top Margin
; $aUseableMonitorMargins[x][3] = Bottom Margin
Func _GetMonitorMargins()
; Alles auf True setzen (=Seite ist frei)
For $i = 1 To $aAllScreenswithDimensions[0][0]
For $j = 0 To 3
$aUseableMonitorMargins[$i][$j] = True
Next
Next
;Jetzt die auf False setzen die an einen anderen Monitor stoßen (Testen immer 10 Pixel in die Richtung, daher +/- 10)
;Wir prüfen vom Mittelpunkt einen Monitors mit +/- 200 Pixel Toleranz nach oben/unten oder links/rechts
For $i = 1 To $aAllScreenswithDimensions[0][0]
For $j = 1 To $aAllScreenswithDimensions[0][0]
If $i <> $j Then ; gegen sich selbst müssen wir nicht prüfen
; Horizontale Prüfungen - ausgehend von der vertikalen Mitte ( /2 ) , Toleranz 200 Pixel nach oben oder unten ( + oder - 200)
If $aAllScreenswithDimensions[$i][3] < ($aAllScreenswithDimensions[$j][3] + ($aAllScreenswithDimensions[$j][1] / 2) - 200) And _
($aAllScreenswithDimensions[$i][3] + $aAllScreenswithDimensions[$i][1]) > ($aAllScreenswithDimensions[$j][3] + ($aAllScreenswithDimensions[$j][1] / 2) + 200) Then
; Ist neben dem linken Rand etwas?
If ($aAllScreenswithDimensions[$i][2] - 10) < ($aAllScreenswithDimensions[$j][2] + $aAllScreenswithDimensions[$j][0]) And _
($aAllScreenswithDimensions[$i][2] - 10) > $aAllScreenswithDimensions[$j][2] Then
$aUseableMonitorMargins[$i][0] = False
$aUseableMonitorMargins[$j][1] = False
EndIf
; Ist neben dem rechten Rand etwas?
If ($aAllScreenswithDimensions[$i][2] + $aAllScreenswithDimensions[$i][0] + 10) > $aAllScreenswithDimensions[$j][2] And _
($aAllScreenswithDimensions[$i][2] + $aAllScreenswithDimensions[$i][0] + 10) < ($aAllScreenswithDimensions[$j][2] + $aAllScreenswithDimensions[$j][0]) Then
$aUseableMonitorMargins[$i][1] = False
$aUseableMonitorMargins[$j][0] = False
EndIf
EndIf
; Vertikale Prüfungen - ausgehend von der horizontalen Mitte ( /2), Toleranz 200 Pixel nach links oder rechts ( + oder - 200)
If $aAllScreenswithDimensions[$i][2] < ($aAllScreenswithDimensions[$j][2] + ($aAllScreenswithDimensions[$j][0] / 2) - 200) And _
($aAllScreenswithDimensions[$i][2] + $aAllScreenswithDimensions[$i][0]) > ($aAllScreenswithDimensions[$j][2] + ($aAllScreenswithDimensions[$j][0] / 2) + 200) Then
; Ist oben etwas?
If ($aAllScreenswithDimensions[$i][3] - 10) < ($aAllScreenswithDimensions[$j][3] + $aAllScreenswithDimensions[$j][1]) And _
($aAllScreenswithDimensions[$i][3] - 10) > $aAllScreenswithDimensions[$j][3] Then
$aUseableMonitorMargins[$i][2] = False
$aUseableMonitorMargins[$j][3] = False
EndIf
; Ist unten etwas?
If ($aAllScreenswithDimensions[$i][3] + $aAllScreenswithDimensions[$i][1] + 10) > $aAllScreenswithDimensions[$j][3] And _
($aAllScreenswithDimensions[$i][3] + $aAllScreenswithDimensions[$i][1] + 10) < ($aAllScreenswithDimensions[$j][3] + $aAllScreenswithDimensions[$j][1]) Then
$aUseableMonitorMargins[$i][3] = False
$aUseableMonitorMargins[$j][2] = False
EndIf
EndIf
EndIf
Next
Next
EndFunc
; #FUNCTION# ====================================================================================================================
; Name ..........: _GetMonitors
; Description ...:
; Syntax ........: _GetMonitors()
; Parameters ....:
; Return values .: Array[0][0] with number of Monitors,
; Array[x][0] Monitor X Screen wide
; Array[x][1] Monitor X Screen height
; Array[x][2] Monitor X Screen Position X
; Array[x][3] Monitor X Screen Position Y
; Author ........: AspirinJunkie
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........: https://autoit.de/index.php?page…1717#post101717
; Example .......: No
; ===============================================================================================================================
Func _GetMonitors()
Local $cbMonitorEnumProc = DllCallbackRegister("MonitorEnumProc", "ubyte", "ptr;ptr;ptr;int")
If @error Then Return SetError(1, 0, False)
Local $strctCount = DllStructCreate("uint Count;uint Width[12];uint Height[12];int left[12];int top[12]")
If @error Then Return SetError(2, @error, False)
Local $iCount
DllStructSetData($strctCount, "Count", 0)
[/autoit] [autoit][/autoit] [autoit]$Ret = DllCall("User32.dll", "ubyte","EnumDisplayMonitors","ptr", 0,"ptr", 0, "ptr", DllCallbackGetPtr($cbMonitorEnumProc), "ptr", DllStructGetPtr($strctCount))
If @error Or $Ret[0] = 0 Then Return SetError(3, @error, False)
DllCallbackFree($cbMonitorEnumProc)
[/autoit] [autoit][/autoit] [autoit]$iCount = Int(DllStructGetData($strctCount, "Count"))
[/autoit] [autoit][/autoit] [autoit]Local $aMonitors[$iCount+1][4] = [[$iCount]]
[/autoit] [autoit][/autoit] [autoit]For $i = 1 To $iCount
$aMonitors[$i][0] = Int(DllStructGetData($strctCount, "Width",$i))
$aMonitors[$i][1] = Int(DllStructGetData($strctCount, "Height",$i))
$aMonitors[$i][2] = Int(DllStructGetData($strctCount, "left",$i))
$aMonitors[$i][3] = Int(DllStructGetData($strctCount, "top",$i))
Next
Return $aMonitors
EndFunc
Func MonitorEnumProc($hMonitor, $hdcMonitor, $lprcMonitor, $dwData)
Local $strctRECT = DllStructCreate("long left;long top;long right;long bottom", $lprcMonitor)
Local $strctCount = DllStructCreate("uint Count;uint Width[12];uint Height[12];int left[12];int top[12]", $dwData)
Local $iNumber = DllStructGetData($strctCount, "Count")
Local $Height = Int(DllStructGetData($strctRECT, "bottom"))-Int(DllStructGetData($strctRECT, "top"))
Local $Width = Int(DllStructGetData($strctRECT, "right"))-Int(DllStructGetData($strctRECT, "left"))
DllStructSetData($strctCount, "Width", $Width, $iNumber+1)
DllStructSetData($strctCount, "Height", $Height, $iNumber+1)
DllStructSetData($strctCount, "left", Int(DllStructGetData($strctRECT, "left")), $iNumber+1)
DllStructSetData($strctCount, "top", Int(DllStructGetData($strctRECT, "top")), $iNumber+1)
DllStructSetData($strctCount, "Count", $iNumber+1)
Return True
EndFunc
; ===============================================================================================================================
Für die Darstellung über Labels habe ich mich entschieden weil ich so Text und Box in einem Objekt habe,
die Ränder werden mit Buutons dargestellt im Vorgiff auf ein Benutzer-Setup was ich damit realisieren möchte.
Wie immer freue ich mich auf eure Verbesserungsvorschläge
BLinz