Jump to content
Sign in to follow this  
bobchernow

Multiple monitor change resolution

Recommended Posts

bobchernow

Hello, first let me say, I am an old programmer but new to Autoit. I am trying to perform a simple task in a new way. What I am trying to do is create a macro that will toggle between two states. I have a laptop and a secondary monitor. Sometimes it is attached, sometimes not. This macro should detect which situation I am in and toggle. Actually it is simpler than that. Assume that if the Secondary monitor is enabled and I am invoking the macro, I want to disable it. If it is currently disabled, I want to enable it, AND set the secondary monitor to 1680*1050 resolution.

I have done this in previous macro languages in a very cludgey way by invoking the Control Panel Display Properties dialog, and simulating a ton of keystrokes. It works most of the time.

I was hoping to get a better solution with AutoIT.

My first attempt was to do the same as before, using the dialog, but feeding the controls directly to avoid sending keystrokes. This effort was somewhat stalled, since the dialog is using a non-standard control for the Monitor Display (Monitor32). Also, I am not sure how to access the sliders, and other control fields since they are not something I created with GUICreate. I think I can use some of the CtrlxXXX functions but I help up on that when I saw that there might be a way to just do it programmatically using WinEnumDisplaySettings, and WinChangeDisplaySettings.

But I am struggling with that a little too. I know if I spend enough time, rewriting the UDF functions, I probably could get the ChangeDisplaySetting function to work with the multiple monitors, but I was hoping not to have to re-invent the wheel if possible.

So, short story long, anybody got something to do this already, or at least what pitfalls I should avoid.

Oh, and this AutoIT stuff is a blast!!!!

Bob Chernow

Edited by bobchernow

--------------------bobchernow, Bob ChernowWhat a long strange trip it's beenUDFs: [post="635594"]Multiple Monitor Screen Resolution Change[/post]

Share this post


Link to post
Share on other sites
PsaltyDS

Hello, first let me say, I am an old programmer but new to Autoit. I am trying to perform a simple task in a new way. What I am trying to do is create a macro that will toggle between two states. I have a laptop and a secondary monitor. Sometimes it is attached, sometimes not. This macro should detect which situation I am in and toggle. Actually it is simpler than that. Assume that if the Secondary monitor is enabled and I am invoking the macro, I want to disable it. If it is currently disabled, I want to enable it, AND set the secondary monitor to 1680*1050 resolution.

I have done this in previous macro languages in a very cludgey way by invoking the Control Panel Display Properties dialog, and simulating a ton of keystrokes. It works most of the time.

I was hoping to get a better solution with AutoIT.

My first attempt was to do the same as before, using the dialog, but feeding the controls directly to avoid sending keystrokes. This effort was somewhat stalled, since the dialog is using a non-standard control for the Monitor Display (Monitor32). Also, I am not sure how to access the sliders, and other control fields since they are not something I created with GUICreate. I think I can use some of the CtrlxXXX functions but I help up on that when I saw that there might be a way to just do it programmatically using WinEnumDisplaySettings, and WinChangeDisplaySettings.

But I am struggling with that a little too. I know if I spend enough time, rewriting the UDF functions, I probably could get the ChangeDisplaySetting function to work with the multiple monitors, but I was hoping not to have to re-invent the wheel if possible.

So, short story long, anybody got something to do this already, or at least what pitfalls I should avoid.

Oh, and this AutoIT stuff is a blast!!!!

Bob Chernow

Search the forum for existing WMI scripts to control video settings. I'm pretty sure you can get a collection object of displays, then run a For/In/Next loop to change them.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
PsaltyDS

After a PM, I went back and looked inside the ChangeResolution.au3 UDF. The user32.dll call to ChangeDisplaySettings in the ChangeResolution UDF will only change the default display device. The DLL call needs to be changed to use ChangeDisplaySettingsEx instead. Then it can specify the target display device.

I don't have the multi-monitor setup to develop and test on, and someone may have already posted it. A quickie search didn't find any reference to ChangeDisplaySettingsEx. Anybody know where it's already been done? I can find references to getting the current resolution (usually citing Larry's GetSystemMetrics usage), but not for setting them.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
bobchernow

Search the forum for existing WMI scripts to control video settings. I'm pretty sure you can get a collection object of displays, then run a For/In/Next loop to change them.

:)

This group is great. PSaltyDS, pointed me to the ChangeDisplaySettingsEx function and it works great. I have modified the original ChangeScreenResolution.au3 and created a ChangeScreenResolutionEx.au3 using the new call and a parameter that allow you to pass in which monitor you want to change resolution for. It works. I have not had time to see if it works in all situations yet, but will share it if anyone is interested.

Now, all I need is to figure out how to disable the secondary monitor so I can swich back to single display mode before I detach the laptop.

Oh, this is so much fun.

Thanks!

Bob :lmao:


--------------------bobchernow, Bob ChernowWhat a long strange trip it's beenUDFs: [post="635594"]Multiple Monitor Screen Resolution Change[/post]

Share this post


Link to post
Share on other sites
PsaltyDS

This group is great. PSaltyDS, pointed me to the ChangeDisplaySettingsEx function and it works great. I have modified the original ChangeScreenResolution.au3 and created a ChangeScreenResolutionEx.au3 using the new call and a parameter that allow you to pass in which monitor you want to change resolution for. It works. I have not had time to see if it works in all situations yet, but will share it if anyone is interested.

Now, all I need is to figure out how to disable the secondary monitor so I can swich back to single display mode before I detach the laptop.

Oh, this is so much fun.

Thanks!

Bob :)

Please do post your UDF. You might add it to the topic in the Example Scripts forum, but you have to have a certain number of posts before you put anything there. If you post it here, I'll make sure it gets in there also.

:lmao:


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
bobchernow

Please do post your UDF. You might add it to the topic in the Example Scripts forum, but you have to have a certain number of posts before you put anything there. If you post it here, I'll make sure it gets in there also.

:)

OK, Here goes. This is my first UDF so be gentle.

#include-once
;===============================================================================
; Function Name:    _ChangeScreenResEx()
; 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
;===============================================================================
Func _ChangeScreenResEx($i_DisplayNum = 1, $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; 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
    
    Local $B = DllCall("user32.dll", "int", "EnumDisplaySettings", "ptr", 0, "int", 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", "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;==>_ChangeScreenResEx

And here is what I have been using to test it.

#include <ChangeResolutionEx.au3>

_ChangeScreenResEx(1,1024,600,-1,-1)
_ChangeScreenResEx(2,1680,1050,-1,-1)

I am still struggling with the DetachMonitorEx.Au3 UDF but I hope to get that working soon. It seems to involve mucking with the $DEVMODE flags and then calling the ChangeDisplaySettingsEx twice, but it is not working as of now.

Bob


--------------------bobchernow, Bob ChernowWhat a long strange trip it's beenUDFs: [post="635594"]Multiple Monitor Screen Resolution Change[/post]

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
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.