Tumulus

Returning Maximum Values of Arrays

4 posts in this topic

#1 ·  Posted (edited)

So I am retrieving monitor details and need to get the maximum resolution possible for the monitor.  So far I have the following code. It was originally a single array returning both vertical and horizontal resolutions together, but I was having trouble returning the last value of the array, so changed it to return two different arrays. I want to return the maxes for each and assign them to two different variables. I now have two issues however. Neither array will display even though I use the _ArrayDisplay function. Also, I am getting an error in the For statements finding the maxes at the end of the code.

#include <Array.au3>
#include <File.au3>

Global $sTempFile=@ScriptDir&'\~scriptomatic.tmp'
Global $aResultH[0]
Global $aResultV[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
    Next
    $hTmp=FileOpen($sTempFile,2)
    FileWrite($hTmp,$OutputH)
    FileClose($hTmp)
    _FileReadToArray($sTempFile,$aResultH,$FRTA_NOCOUNT, @TAB)
    _ArrayDisplay($aResultH)
    FileDelete($sTempFile)

Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "CIM_VideoControllerResolution")
EndIf

IF IsObj($colItems) Then
    For $objItem In $colItems
        $OutputV = $OutputV & $objItem.VerticalResolution & @CRLF
    Next
    $vTmp=FileOpen($sTempFile,2)
    FileWrite($vTmp,$OutputV)
    FileClose($vTmp)
    _FileReadToArray($sTempFile,$aResultV,$FRTA_NOCOUNT, @TAB)
    _ArrayDisplay($aResultV)
    FileDelete($sTempFile)

Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "CIM_VideoControllerResolution")
EndIf

Local $i = 0
Local $j = 0
Local $iMaxHorizontal = 0
Local $iMaxVertical = 0

For $aObj in $aResultH
        If $aResultH[$i] > $iMaxHorizontal Then
        $iMaxHorizontal = $aResultH[$i]
        $i = $i + 1
        EndIf
Next

For $aObj in $aResultV
        If $aResultV[$j] > $iMaxVertical Then
        $iMaxVertical = $aResultV[$j]
        $j = $j + 1
        EndIf
Next

Any help would be very appreciated. :) 

Edited by Tumulus

Share this post


Link to post
Share on other sites



Here's a better way to do it, that actually works and doesn't require writing/reading a file.

#include <Array.au3>
#include <File.au3>

Global $sTempFile = @ScriptDir & '\~scriptomatic.tmp'
Global $aResultH[0]
Global $aResultV[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
    $aResultH = StringSplit($OutputH, @CRLF, 1)
    $aResultV = StringSplit($OutputV, @CRLF, 1)

    _ArrayDisplay($aResultH)
    _ArrayDisplay($aResultV)
    FileDelete($sTempFile)

Else
    MsgBox(0, "WMI Output", "No WMI Objects Found for class: " & "CIM_VideoControllerResolution")
EndIf


Local $i = 0
Local $j = 0
Local $iMaxHorizontal = 0
Local $iMaxVertical = 0
$iMaxHorizontal = _ArrayMax($aResultH, 1)
$iMaxVertical = _ArrayMax($aResultV, 1)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iMaxVertical = ' & $iMaxVertical & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iMaxHorizontal = ' & $iMaxHorizontal & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

 


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 Gude
How 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

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Thanks! I got that from scriptomatic and was really confused why there needed to be a file opened. I figured there was a better way to assign values to an array, but I asked a few colleagues and none was familiar enough with AutoIT to give me the right direction. Thanks! 

And just for understanding; the StringSplit function just parses the data for inclusion in the array?

Edited by Tumulus

Share this post


Link to post
Share on other sites

So I have edited the script above and it helped a ton. I added it to the following script that detects monitor details and sets the max resolution. I am actually getting it to work (sort of). I work on a 3 monitor setup so did some testing there. The settings are read for monitor 1 but then change on monitor two. We are applying the script to computers with a single monitor, so I figured I would try it on a single monitor setup, but it won't work at all there.

I feel like I might be changing the resolution on a different monitor than the monitor I am getting the data from, but I can't find anything in my code that would cause that. My GetRes function is taken from a thread on the forum. The function was coded by @MrYonG.

#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

 

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.


Sign In Now