Jump to content

Setting Windows Display Scale Percentage on the Fly without Reboot or Logout


Davegbuf
 Share

Recommended Posts

I have been using AutoIt for a long time but what I would like to do here is a bit above my understanding. I am hoping that someone with more knowledge about AutoIt and PowerShell than myself can help translate the three main command-lines so that I can develop it into an AutoIt function. This would allow more flexibly and integration with my existing AutoIt code projects. 

Background Info: I have a Powershell script that can change the Windows display scale percentage on the fly without having to reboot or log off. My knowlege of Powershell is very basic, so what I did was modify the original PowerShell script as you can see in the attached screenshot below. This changes the dispaly scale to 125% when I run it in natively. As you can also see, I created a variable called $scaling and assigned it a value of 1 to make it a straight script because I don't know how to pass values to it externally from a BAT or AutoIt script as-is. 

Observations:

It seems like the only thing the PS script does is get some info from the user32.dll and then do a couple of API calls. I noticed that AutoIt has a _WinAPI_SystemParametersInfo() and DllCall() functions which I think would work the same way antively in AutoIt. The problem for me is that the Help Information, the MSDN website info, and Powershell information on the internet is very confusing and I don't understand it very well. I am a PC administrator, and not a developer so many of these programming concepts are aove my understanding.

I would like to do the same as the PS1 script in Autoit. If anyone can help me with those few lines, I can create a function out of it that I would gladly share with the AutoIt community.

 

Original Powershell script source:
https://stackoverflow.com/questions/10365394/change-windows-font-size-dpi-in-powershell/68760240#68760240Set_Scale.PS1_Script.thumb.png.6a047eea013387e2be42fd38266dbcc3.png

Set_Scale.ps1

Link to comment
Share on other sites

On 7/12/2023 at 2:44 PM, Andreik said:
_WinAPI_SystemParametersInfo(0x009F, $iScaling, Null, 0x0001)

 

Andreik, I saw your reply over the weekend, and I was very excited to give it a try. You did exactly what I needed with one single line of code and it is much simpler than the original PowerShell script. It worked so well that I made a command line utility with a function where I could scale my laptop display to any percentage by passing a string as a parameter like: 100%, 125%, 150%, 175% or it’s equivalent numerical value 0,1,2, or 3. I’m afraid it will not be very useful as-is. Nonetheless, I included it further towards the end so you can see it.

The problem is that I think I discovered why the MSDN site has a note for SPI_SETLOGICALDPIOVERRIDE that says Do not use. When I ran the same script on a different laptop, the values I passed would give different results. For example, I might use the 125% value, and the machine would scale to 175% instead. Here is an interesting read on that undocumented Microsoft feature:   https://stackoverflow.com/questions/35233182/how-can-i-change-windows-10-display-scaling-programmatically-using-c-sharp/62916586#62916586

I bookmarked the articles to circle back later when I can free up some spare time. In short, it looks like the values 0 – 3 are index values relative to a specific value that represents the OS “recommended” percentage for the display. For example, the screenshot below shows 100% is recommended for the machine; therefore, 0 represents the recommended value index. If I use your line of code a value of 1 as seen below, then the display scales to the next step up, 125%. 

_WinAPI_SystemParametersInfo(0x009F,1, Null, 0x0001)

The other laptop where my test failed has a recommended value of 150%, so I can run the same script with a value of -1 as seen below to bring it to 125% since this percentage is the next step below the recommended (0 index) value.

_WinAPI_SystemParametersInfo(0x009F,-1, Null, 0x0001)

 

The same article writer explains more in this article which I added an excerpt below. https://stackoverflow.com/questions/35233182/how-can-i-change-windows-10-display-scaling-programmatically-using-c-sharp/58066736#58066736

Note on DPI scaling on windows

1.       DPI scaling is property of the source and not of target (see ViPN for these terminologies).

2.       DPI scaling of a display is dependent on 3 factors - resolution, physical size of display, expected viewing distance. The exact formula which Windows uses to arrive at recommended value is unknown.

3.       In OS parlance DPI scaling values have a meaning when compared against the recommended DPI scaling of a display. Thus although we see 100%, 125%, etc. in system settings app, the OS doesn't understand scaling in percentages. Instead number of steps above, or below recommended scaling is used. For eg. a DPI scaling value of -1 would mean 1 step lower than the recommended DPI scaling. So if for a monitor the recommended value is 150%, -1 would mean 125%.

 I used WinDbg Preview (MS Store), and Ghidra to do the reverse engineering. There was a point when I was about to give up for the lack of IDA Pro license, when someone suggested me Ghidra. I have been a fan ever since.

 

 

First  Draft

#AutoIt3Wrapper_UseX64=y
#include <WinAPISys.au3>

; --- (NOTE: Cannot scale Display on a Terminal Services (RDP) session. The environment variable SESSIONNAME will be Null("")
;      on the current machine if running in a Terminal Services session; or "Console" id running on a computer standard session.

       If EnvGet('SESSIONNAME')<>'Console' Then
              MsgBox(16,'Session Error','Cannot scale Display on a Terminal Services (RDP) session.',60)
              Exit(-1)
       EndIf

  ; --- Set Display Scale Percentage according to the value passed via the command line.
  If $CmdLine[0]=1 Then $bReturn=_SetWinDisplayScalePercent($CmdLine[1])

  If $CmdLine[0]<>1 OR $bReturn=False Then
       MsgBox(16,'Syntax Error','Syntax:' & @CRLF & @CRLF & 'Set_Windows_Display_Scale_Percent.exe [value | percentage]' & @CRLF & @CRLF _
              & '   "0" or "100%"  (default)' & @CRLF & '   "1" or "125%"' & @CRLF & '   "2" or "150%"' & @CRLF & '   "3" or "175%"' _
              & @CRLF & @CRLF & 'Example 1 - Set scale to 125% : ' & @CRLF & @CRLF & '     Set_Windows_Display_Scale_Percent.exe 125%' & @CRLF & @CRLF _
              & 'Example 2 - Set scale to 150% using value 2 :' & @CRLF & @CRLF & '     Set_Windows_Display_Scale_Percent.exe 2',60)
  Endif

 Exit

; #FUNCTION# ====================================================================================================================
; Script Function: Change the Windows Display Scale Percentage on the fly without the need to reboot. Unlike other
;                     solutions found on the internet which require modifying the registry and a system reboot, this
;                     solution takes effect immediately.
;  This AutoIt function is a conversion based on an original Powershell script that was posted on the internet
;      by IanXue-MSFT on https://learn.microsoft.com/en-us/answers/questions/197944/batch-file-or-tool-like-powertoy-to-change-the-res.html
; ------------------------------------------------------------------------------------------------------------------------------
; -- Sets the Display Scale Percentage to 100% or optionally to the value specified by $iScale
;
;      _SetWinDisplayScalePercent([$iScale=0])
;
;   Parameter $iScale:
;    # $iScale = 0 : 100% (default)
;    # $iScale = 1 : 125%
;    # $iScale = 2 : 150%
;    # $iScale = 3 : 175%
;
;   Return Value - Returns True (success) or False (failed) as returned by _WinAPI_SystemParametersInfo()
;   Returns @error and extended as returned by _WinAPI_SystemParametersInfo()
;
; ===============================================================================================================================

 Func _SetWinDisplayScalePercent($ScalePercent='')

       Select
              Case $ScalePercent='' OR $ScalePercent='0' OR $ScalePercent='100%'
                     $iScale=0    ; --- Default
              Case $ScalePercent='1' OR $ScalePercent='125%'
                     $iScale=1
              Case $ScalePercent='2' OR $ScalePercent='150%'
                     $iScale=2
              Case $ScalePercent='3' OR $ScalePercent='175%'
                     $iScale=3
              Case Else
                     Return SetError(-1,-1,False)
       EndSelect

        ; --- Set the Display Scale
             ; SPI_SETLOGICALDPIOVERRIDE = 0x009F
             ; SPIF_UPDATEINIFILE = 0x0001

        $iReturn=_WinAPI_SystemParametersInfo(0x009F, $iScale, Null, 0x0001) ; --- set the display to the selected scale percentage

        ; --- Return results
       Return SetError(@error,@extended,$iReturn)

 EndFunc             ; end _SetWinDisplayScalePercent()

; ===============================================================================================================================

 

 

 

 

Edited by Davegbuf
Edited to make the post more legible.
Link to comment
Share on other sites

  • 7 months later...

Hi @Davegbuf, I would love to steal your script for my own use. I have a 4k monitor and when Im working alone, I like it at 150% but when Im sharing my screen on teams, I need to quickly change it to 300% for my coworkers to see it properly. (as an aside, my machine recommends 150% scale so that can be my 0 value as its the one I prefer, then I can set value1 to 300% and remove the other options from my configuration).

How do I implement the script itself? I can see where I would change my settings, but not sure, where to save it and then run it from. 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...