Hallo zusammen,
ich habe ein Script, welches bei uns im Einsatz ist und bei allen angeschlossenen Bildschirmen die Auflösung auf eine vordefinierte Auflösung ändert.
Das klappt soweit sehr gut.
Verwendetes Script
#Region ;Header
;===============================================================================================================================
;Description......: Set Screen Resolution
;Author...........: Veronesi
;Date.............: 03.09.2010
;===============================================================================================================================
#NoTrayIcon
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_icon=WEY.ico
#AutoIt3Wrapper_Res_Comment=Set Screen Resolution
#AutoIt3Wrapper_Res_Description=Set Screen Resolution
#AutoIt3Wrapper_Res_Fileversion=1.1.0.1
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=Veronesi
Opt("MustDeclareVars", 1) ;Must declare variables
OnAutoItExitRegister("_Exit") ;Create defined Exit Callback Register
_Singleton(@ScriptName) ;Allow only one instance of this script at the same time
HotKeySet("{ESC}","_Exit") ;ESC-Hotkey
HotKeySet("{F8}","_SetResolution") ;ESC-Hotkey
#include-once
#include <Misc.au3>
#EndRegion ;End of Header
;===============================================================================================================================
#Region ;Variables, Constants
Dim Const $ScreenWidth = 2560
Dim Const $ScreenHeight = 1600
Dim Const $BitPP = 32
Dim Const $RefreshRate = 60
Dim $aMonitorInfo
#EndRegion ;End of Variables, Constants
;===============================================================================================================================
#Region ;Main
While 1
Sleep(5000)
WEnd
Exit
#EndRegion ;End of Main
;===============================================================================================================================
#Region ;Functions
Func _SetResolution()
$aMonitorInfo = _GetMonitorInfo()
For $i = 1 To $aMonitorInfo[0][0]
_ChangeScreenRes($i, $ScreenWidth, $ScreenHeight, $BitPP, $RefreshRate)
Next
Return 1
EndFunc ;==>_SetResolution
Func _ChangeScreenRes($i_DisplayNum = 1, $i_Width = @DesktopWidth, $i_Height = @DesktopHeight, $i_BitsPP = @DesktopDepth, $i_RefreshRate = @DesktopRefresh)
;===============================================================================
; Function Name: _ChangeScreenRes()
; Description: Changes the current screen geometry, colour and refresh rate.
; Version: 1.0.0.0
; Parameter(s): $i_DisplayNum - Display to change, starting at 1
; $i_Width - Width of the desktop screen in pixels. (horizontal resolution)
; $i_Height - Height of the desktop screen in pixels. (vertical resolution)
; $i_BitsPP - Depth of the desktop screen in bits per pixel.
; $i_RefreshRate - Refresh rate of the desktop screen in hertz.
; Requirement(s): AutoIt Beta > 3.1
; Return Value(s): On Success - Screen is adjusted, @ERROR = 0
; On Failure - sets @ERROR = 1
; Forum(s):
; Author(s): Original code - psandu.ro, PartyPooper
; Modifications - bobchernow
;===============================================================================
Local Const $DM_PELSWIDTH = 0x00080000
Local Const $DM_PELSHEIGHT = 0x00100000
Local Const $DM_BITSPERPEL = 0x00040000
Local Const $DM_DISPLAYFREQUENCY = 0x00400000
Local Const $CDS_TEST = 0x00000002
Local Const $CDS_UPDATEREGISTRY = 0x00000001
Local Const $DISP_CHANGE_RESTART = 1
Local Const $DISP_CHANGE_SUCCESSFUL = 0
Local Const $HWND_BROADCAST = 0xffff
Local Const $WM_DISPLAYCHANGE = 0x007E
If $i_Width = "" Or $i_Width = -1 Then $i_Width = @DesktopWidth; default to current setting
If $i_Height = "" Or $i_Height = -1 Then $i_Height = @DesktopHeight; default to current setting
If $i_BitsPP = "" Or $i_BitsPP = -1 Then $i_BitsPP = @DesktopDepth; default to current setting
If $i_RefreshRate = "" Or $i_RefreshRate = -1 Then $i_RefreshRate = @DesktopRefresh; default to current setting
Local $DEVMODE = DllStructCreate("byte[32];int[10];byte[32];int[6]")
Local $s_Display
$s_Display = "\\.\Display" & $i_DisplayNum
[/autoit] [autoit][/autoit] [autoit]Local $B = DllCall("user32.dll", "int", "EnumDisplaySettings", "ptr", 0, "int", 0, "ptr", DllStructGetPtr($DEVMODE))
[/autoit] [autoit][/autoit] [autoit]If @error Then
$B = 0
SetError(1)
Return $B
Else
$B = $B[0]
EndIf
If $B <> 0 Then
DllStructSetData($DEVMODE, 2, BitOR($DM_PELSWIDTH, $DM_PELSHEIGHT, $DM_BITSPERPEL, $DM_DISPLAYFREQUENCY), 5)
DllStructSetData($DEVMODE, 4, $i_Width, 2)
DllStructSetData($DEVMODE, 4, $i_Height, 3)
DllStructSetData($DEVMODE, 4, $i_BitsPP, 1)
DllStructSetData($DEVMODE, 4, $i_RefreshRate, 5)
;~ $B = DllCall("user32.dll", "int", "ChangeDisplaySettingsEx","str", $s_Display, "ptr", DllStructGetPtr($DEVMODE), "hwnd", 0, "dword", $CDS_TEST, "lparam", 0)
;~ If @error Then
;~ $B = -1
;~ Else
;~ $B = $B[0]
;~ EndIf
;~ Select
;~ Case $B = $DISP_CHANGE_RESTART
;~ $DEVMODE = ""
;~ Return 2
;~ Case $B = $DISP_CHANGE_SUCCESSFUL
DllCall("user32.dll", "int", "ChangeDisplaySettingsEx","str", $s_Display, "ptr", DllStructGetPtr($DEVMODE), "hwnd", 0, "dword", $CDS_UPDATEREGISTRY, "lparam", 0)
;~ DllCall("user32.dll", "int", "SendMessage", "hwnd", $HWND_BROADCAST, "int", $WM_DISPLAYCHANGE, _
;~ "int", $i_BitsPP, "int", $i_Height * 2 ^ 16 + $i_Width)
$DEVMODE = ""
Return 1
;~ Case Else
;~ $DEVMODE = ""
;~ SetError(1)
;~ Return $B
;~ EndSelect
EndIf
EndFunc;==>_ChangeScreenRes
Func _GetMonitorInfo()
;Returns some informations about your screens
;Call: _GetMonitorInfo()
;Return: Array With
;[0][0] Nr of Monitors
;[1][0] X Resolution of Monitor 1
;[1][1] Y Resolution of Monitor 1
;[1][2] X Position of Monitor 1
;[1][3] Y Position of Monitor 1
;[2][0] X Resolution of Monitor 2
;[2][1] Y Resolution of Monitor 2
;[2][2] X Position of Monitor 2
;[2][3] Y Position of Monitor 2
;......
Local $NrOfMonitors, $ResolutionX[32], $ResolutionY[32], $PositionX[32], $PositionY[32], $Ret
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"))
If @error Then Return SetError(4, @error, False)
Local $aMonitors[$iCount+1][4] = [[$iCount]]
[/autoit] [autoit][/autoit] [autoit]For $i = 1 To $iCount
$aMonitors[$i][0] = Int(DllStructGetData($strctCount, "Width",$i))
If @error Then Return SetError(5, @error, False)
$aMonitors[$i][1] = Int(DllStructGetData($strctCount, "Height",$i))
If @error Then Return SetError(6, @error, False)
$aMonitors[$i][2] = Int(DllStructGetData($strctCount, "left",$i))
If @error Then Return SetError(7, @error, False)
$aMonitors[$i][3] = Int(DllStructGetData($strctCount, "top",$i))
If @error Then Return SetError(8, @error, False)
Next
$strctCount = 0
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)
If @error Then Return SetError(9, @error, False)
DllStructSetData($strctCount, "Height", $Height, $iNumber+1)
If @error Then Return SetError(10, @error, False)
DllStructSetData($strctCount, "left", Int(DllStructGetData($strctRECT, "left")), $iNumber+1)
If @error Then Return SetError(11, @error, False)
DllStructSetData($strctCount, "top", Int(DllStructGetData($strctRECT, "top")), $iNumber+1)
If @error Then Return SetError(12, @error, False)
DllStructSetData($strctCount, "Count", $iNumber+1)
If @error Then Return SetError(13, @error, False)
Return True
EndFunc
Func _Exit()
HotKeySet("{ESC}") ;Delete Hotkey
HotKeySet("{F8}") ;Delete Hotkey
Exit
EndFunc ;==>_Exit
#EndRegion ;End of Functions
Das Problem ist nun, dass wir im laufenden PC Betrieb die Monitore abhängen und neue anschliessen müssen. (Kabel und Monitor Test)
Da pro Tag über 500 neue Monitore an diesen Testplatz angeschlossen werden, können wir nicht jedes mal den PC neu starten. Auf dem PC ist Win7 64bit.
In 460 von 500 Fällen erkennt Windows automatisch die Monitore und stellt die Auflösung korrekt ein. In den restlichen Fällen kommt mein Script zum Einsatz, welches per F8 Hotkey die Auflösung setzt. Das klappt auch - aber "bloss" in 80% der Fällen.
Manchmal kann die Auflösung per Script einfach nicht gesetzt werden. (Auch wenn man es mehrmals hintereinander versucht)
Es kommt auch kein Fehler oder so von der Funktion zurück! (Fehlerbehandlung ist in diesem Script wieder gelöscht worden)
Geht man dann aber manuell in die Systemsteuerung und stellt es dort ein, dann geht es. D.h. Windows selber kann es, aber mein Script nicht.
1. Frage: Warum kann das mein Script manchmal nicht? Sieht jemand einen unbehandelten Fehler?
2. Frage: Manchmal kommt beim starten des Scripts oder auch während der Laufzeit einen AutoIt Error mit der Meldung, dass eine (Array) Variable benutzt wurde, die noch nicht definiert ist. Findet jemand den Fehler?
Manchmal habe ich das Gefühl, wenn man das Script lange laufen lässt, und dann beendet und sofort so schnell wie möglich das Script neu startet, dass dann dieser Fehler öfters auftaucht. Wie wenn noch was im Speicher wäre...
Hinweis: Die auskommentierten Zeilen in der Funktion _ChangeScreenRes habe ich auch schon drin gehabt. Es tauchen die gleichen sporadischen Fehler auf.
Vielen Dank!
Veronesi