Tumulus Posted April 27, 2016 Posted April 27, 2016 So I am working on a script to change the resolution on my monitor to reflect the maximum setting it can possibly support. I am using it for single monitor displays, but testing it on my 3 monitor set up at work. When I test it there, the settings for monitor one are detected, but then the change applies to monitor two. If I test it on a single monitor computer it correctly identifies the maximum setting for the monitor, but never applies it. The message box I included to test the ChangeRes function never shows in either case. I assume that I am changing the monitor settings for a different monitor than the one I am taking the setting data from, but I am not sure exactly where in my code that error is (if that is truly the case). If you could give it a look over and help me find the mistake I would be much obliged. My experience with structs is very minimal. The ChangeRes function is taken from the function written by Mr. YonG in this thread. expandcollapse popup#include <Array.au3> #include <File.au3> ;Default entries $OKMSGBOX = 0 $DEFAULT = "" ;program variables Global $i_WidthScreen Global $i_HeightScreen ;GetRes finds the maximum supported resolution setting on the monitor Func GetRes(ByRef $i_WidthScreen, ByRef $i_HeightScreen) Local $i_MaxHorizontal Local $i_MaxVertical Local $a_ResultH[0] Local $a_ResultV[0] $wbemFlagReturnImmediately = 0x10 $wbemFlagForwardOnly = 0x20 $colItems = "" $sComputer = "localhost" $OutputH = "" $OutputV = "" $oWMIService = ObjGet("winmgmts:\\" & $sComputer & "\") $colItems = $oWMIService.ExecQuery("SELECT * FROM CIM_VideoControllerResolution", "WQL", _ $wbemFlagReturnImmediately + $wbemFlagForwardOnly) If IsObj($colItems) Then For $objItem In $colItems $OutputH = $OutputH & $objItem.HorizontalResolution & @CRLF $OutputV = $OutputV & $objItem.VerticalResolution & @CRLF Next $a_ResultH = StringSplit($OutputH, @CRLF, 1) $a_ResultV = StringSplit($OutputV, @CRLF, 1) ;_ArrayDisplay($aResultH) ;these are for testing purposes to make sure the arrays populate correctly ;_ArrayDisplay($aResultV) Else MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "CIM_VideoControllerResolution") EndIf $i_MaxHorizontal = _ArrayMax($a_ResultH, 1) $i_MaxVertical = _ArrayMax($a_ResultV, 1) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $i_MaxVertical = ' & $i_MaxVertical & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $i_MaxHorizontal = ' & $i_MaxHorizontal & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console $i_WidthScreen = $i_MaxHorizontal $i_HeightScreen = $i_MaxVertical ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $i_WidthScreen = ' & $i_WidthScreen & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $i_HeightScreen = ' & $i_HeightScreen & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console ;MsgBox($OKMSGBOX, "GetRes", "The Get Resolution function resolved") ;This is for testing to make sure the funct ran properly EndFunc;==>GetRes ;ChangeRes changes the resolution settings Func ChangeRes($i_Width = @DesktopWidth, $i_Height = @DesktopHeight, $i_BitsPP = @DesktopDepth, $i_RefreshRate = @DesktopRefresh) 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 EndIf If $i_Height = "" Or $i_Height = -1 Then $i_Height = @DesktopHeight EndIf If $i_BitsPP = "" Or $i_BitsPP = -1 Then $i_BitsPP = @DesktopDepth EndIf If $i_RefreshRate = "" Or $i_RefreshRate = -1 Then $i_RefreshRate = @DesktopRefresh EndIf Local $DEVMODE = DllStructCreate("byte[32];int[10];byte[32];int[6]") Local $B = DllCall("user32.dll", "int", "EnumDisplaySettings", "ptr", 0, "long", 0, "ptr", DllStructGetPtr($DEVMODE)) 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", "ChangeDisplaySettings", "ptr", DllStructGetPtr($DEVMODE), "int", $CDS_TEST) 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", "ChangeDisplaySettings", "ptr", DllStructGetPtr($DEVMODE), "int", $CDS_UPDATEREGISTRY) 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 MsgBox($OKMSGBOX, "Change Resolution", "The screen resolution has been set to " & $i_WidthScreen & "x" & $i_HeightScreen) EndFunc ;==> ChangeRes ;Main prog- runs the above functions GetRes($i_WidthScreen, $i_HeightScreen) ChangeRes($i_WidthScreen, $i_HeightScreen, $DEFAULT, $DEFAULT) ;End prog
BrewManNH Posted April 27, 2016 Posted April 27, 2016 In the DEVMODE struct you need to give it a dmPosition setting to change it to the monitor you're attempting to change the resolution of. dmPosition is a pointer to a struct that tells it what the POINTL coordinates are. If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag GudeHow to ask questions the smart way! I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from. Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays. - ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script. - Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label. - _FileGetProperty - Retrieve the properties of a file - SciTE Toolbar - A toolbar demo for use with the SciTE editor - GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI. - Latin Square password generator
Tumulus Posted April 28, 2016 Author Posted April 28, 2016 Alright. I think I have made the changes, but like I said, structs are still a bit beyond my capabilities for the moment. Is this right? I added another int variable to my $DEVMODE struct and set it equal to the value for $DM_POSITION. I also added it to the part of the struct that references the other DM variables. It didn't change anything though (still getting the change on the 2nd monitor), so I must be missing something in the DllCall or I did it incorrectly. (I was quite confused that four different values were assigned to element 4 each with a different index. Also that element 2 has a BitOr combining the 5 values) After researching the pages you provided above, I tried setting the struct a different way in the commented out section but that did not work either, and the values displayed by the message box changed completely. I think that they may not be assigned in the correct order. What am I not understanding here? Is there a struct concept or a Dll concept that I am not grasping? (I certainly think that is the case). expandcollapse popupLocal $DEVMODE = DllStructCreate("byte[32];int[10];byte[32];int[6];int") IF @error Then MsgBox($OKMSGBOX, "", "Error in DllStructCreate, code: " & @error) Return False EndIf Local $B = DllCall("user32.dll", "int", "EnumDisplaySettings", "ptr", 0, "long", 0, "ptr", DllStructGetPtr($DEVMODE)) If @error Then $B = 0 SetError(1) Return $B Else $B = $B[0] EndIf If $B <> 0 Then ;#cs DllStructSetData($DEVMODE, 2, BitOR($DM_PELSWIDTH, $DM_PELSHEIGHT, $DM_BITSPERPEL, $DM_DISPLAYFREQUENCY, $DM_POSITION), 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) DllStructSetData($DEVMODE, 5, $DM_POSITION) #ce #cs DllStructSetData($DEVMODE, 1, $i_Width) DllStructSetData($DEVMODE, 2, $i_Height) DllStructSetData($DEVMODE, 3, $i_BitsPP) DllStructSetData($DEVMODE, 4, $i_RefreshRate) DllStructSetData($DEVMODE, 5, $DM_POSITION) #ce ;Testing portion to view my struct MsgBox(1, "", "Struct Size: " & DllStructGetSize($DEVMODE) & @CRLF & _ "Struct pointer: " & DllStructGetPtr($DEVMODE) & @CRLF & _ "Data:" & @CRLF & _ DllStructGetData($DEVMODE, 1) & @CRLF & _ DllStructGetData($DEVMODE, 2) & @CRLF & _ DllStructGetData($DEVMODE, 3) & @CRLF & _ DllStructGetData($DEVMODE, 4) & @CRLF & _ DllStructGetData($DEVMODE, 5))
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now