Tumulus Posted April 27, 2016 Share 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 Link to comment Share on other sites More sharing options...
BrewManNH Posted April 27, 2016 Share 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 Link to comment Share on other sites More sharing options...
Tumulus Posted April 28, 2016 Author Share 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)) Link to comment Share on other sites More sharing options...
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