0

I have an HP Spectre x360 13 laptop running Windows 10. The default resolution for the display is 3480 x 2160, with a scaling factor of 300%.

I need to change the resolution to 1920 x 1080 with a scaling factor of 125% for a single application. When I'm done using that application, I need to change it back.

Of course, I can do this manually; right-click on the desktop, change the settings, launch the app, close the app, right-click, change the settings ...

But it seems to me I should be able to write a batch script to do this. I'm only marginally capable of this sort of thing, and in this instance I have no idea what commands to include in the script. Can anyone help?

  • I doubt that this can be done via a batch script, but you may be able t write a program to do this by calling the Win32 API. However, Microsoft have become increasingly averse to programs changing such settings as they feel that the user should be in control of them rather than some random program. (Think what would happen if two such programs did the same thing but with different target settings. Fight club.) – simon at rcl Oct 6 at 10:07
  • 32 or 64-bit Windows10? What command starts the app you want to run? Post a screenshot of your display settings window with the scaling and resolution boxes expanded. – somebadhat Oct 17 at 20:53
0

Here is a Windows 10 64-bit visual basic script and Powershell 5 script.

ScreenCapture of the VBscript in action. (1.1MB mp4)

Windows 10 64-bit visual basic script using SendKeys to change display scale and resolution, open app, and restore scale and resolution when app closes. No restart required.

Copy and paste the code into a new text document. Save it as a .vbs file (i.e. ChangeDisplay.vbs), edit it, and run it.

Changing the scaling and resolution will mess up your desktop icon layout. Download, install, and learn how to use a command line desktop icon layout backup like:

DesktopOK v4.24. Save and restore desktop icon layout from the command line. Put DesktopCmd64.exe somewhere in your PATH, add it to your PATH, or just put it in your windows folder.

and

DesktopRestore v1.6.3.031. Save and restore desktop icon layout from the command line. 64-bit command line version fails occasionally in Windows 10 64-bit? Put DesktopRestore64.exe somewhere in your PATH, add it to your PATH, or just put it in your windows folder.

Edit the script:

Change "PUT THE IMAGENAME OF YOUR APP HERE", "CHANGE THE FOLLOWING {UP} / {DOWN}?", and CHANGE THE COMMAND THAT STARTS YOUR APP.

Open the display settings window explorer ms-settings:display and figure out what combination of TAB and UP or DOWN keystrokes you need to get the setting you want and "CHANGE THE FOLLOWING {UP} / {DOWN}?" If you open the display settings window another way your number of TAB/S might be different.

The Wscript.Sleep timing can be tricky. Both decreasing the sleep and increasing the sleep can break the script. Running the script during times of high disk use can cause the script to fail. There are a lot of different things you can try:

  1. focus at stackoverflow
  2. pause at stackoverflow
  3. Google search - windows 10 wscript wait for process to finish loading

but I am sticking with Wscript.Sleep alone because it is working for me. See comments around Wscript.Sleep 2000.

BEGIN MOSTLY NATIVE USING A VISUAL BASIC SCRIPT

' WINDOWS 10 64-BIT VISUAL BASIC SCRIPT TO CHANGE DISPLAY SCALE AND RESOLUTION, OPEN APP, AND RESTORE SCALE AND RESOLUTION WHEN APP CLOSES.
' https://superuser.com/questions/1489592/windows-10-batch-script-to-change-display-settings-for-specific-application
' All native except DesktopOK and DesktopRestore.  Does not require restart.
' Changing the scaling and resolution will mess up your desktop icon layout.  Download, install, and learn how to use a command line desktop icon layout backup like:
' DesktopOK v4.24. Save and restore desktop icon layout from the command line. https://www.softwareok.com/?Download=DesktopOK    
' Put DesktopCmd64.exe somewhere in your PATH.
' and 
' DesktopRestore v1.6.3.031. Save and restore desktop icon layout from the command line. 64-bit command line version fails occasionally in Windows 10 64-bit? http://www.midiox.com/desktoprestore.htm   
' Put DesktopRestore64.exe somewhere in your PATH.
' Change "PUT THE IMAGENAME OF YOUR APP HERE", "CHANGE THE FOLLOWING {UP} / {DOWN}?", AND CHANGE THE COMMAND THAT STARTS YOUR APP.
' Open the display settings window (explorer ms-settings:display) and figure out what combination of TAB AND UP OR DOWN keystrokes you need to get the setting you want and "CHANGE THE FOLLOWING {UP} / {DOWN}?"
' If you open the display settings window another way your number of TAB/S might be different.

' BEGIN CHANGE TO 1920 X 1080 W/ 100% SCALING
option explicit
DIM strComputer,WshShell,HostName,Ping,FileName,Return
SET WshShell = WScript.CreateObject("WScript.Shell")  

' BEGIN BACKUP DESKTOP ICON LAYOUT 
FileName = "%USERPROFILE%\Desktop\DesktopIconLayout" & timer & ".dok"
WshShell.Run "desktoprestore64.exe /save /silent " & FileName, 0, False
FileName = "%USERPROFILE%\Desktop\DesktopIconLayout" & timer & ".dtr"
WshShell.Run "DesktopCmd64.exe save /f " & FileName, 0, False
'   END BACKUP DESKTOP ICON LAYOUT 

' BEGIN KILL APP
' PUT THE IMAGENAME OF YOUR APP HERE
' I.E. replace iexplore.exe
FileName = "iexplore.exe"
WshShell.Run "taskkill /im " & FileName & " /f", 0, False
'   END KILL APP

' BEGIN CLOSE AND OPEN DISPLAY SETTINGS WINDOW
strComputer = "." ' local computer
FileName = "SystemSettings.exe"
if isProcessRunning(strComputer,FileName) then
WshShell.Run "taskkill /im " & FileName & " /f", 0, False
WshShell.Run "explorer ms-settings:display" 
else
WshShell.Run "explorer ms-settings:display" 
end if
Set strComputer = Nothing
Set FileName = Nothing
'   END CLOSE AND OPEN DISPLAY SETTINGS WINDOW

' You have to give the display settings window enough time to load.
' There are a lot of different things you can try.
' If I change the following Wscript.Sleep to 4 seconds and leave the later one at 2 seconds the script fails
' even though 2 seconds works.
Wscript.Sleep 2000 

' BEGIN CHANGE SCALE
' CHANGE THE FOLLOWING {UP} / {DOWN}?
WshShell.SendKeys "{TAB 2}{DOWN}" 
'   END CHANGE SCALE 

Wscript.Sleep 750 

' BEGIN CHANGE RESOLUTION
' CHANGE THE FOLLOWING {UP} / {DOWN}?
WshShell.SendKeys "{TAB 2}{DOWN}" 
'   END CHANGE RESOLUTION 

Wscript.Sleep 750 

' BEGIN ACCEPT RESOLUTION CHANGE
WshShell.SendKeys "{TAB}" 
Wscript.Sleep 750 
WshShell.SendKeys "{ENTER}" 
'   END ACCEPT RESOLUTION CHANGE

Wscript.Sleep 750 

' BEGIN Return TO THE "FIND A SETTING" BOX.  IMPROVES RELIABILITY.
' BEGIN PROCEDURE CHANGES IF PC IS ON/OFFLINE
' Dim HostName
' HostName = "8.8.8.8"
' Ping = WshShell.Run("Ping -n 1 " & HostName, 0, True)
' Select Case Ping
' Case 0 
' WshShell.SendKeys "{TAB}" ' Online
' Case 1 
' WshShell.SendKeys "{TAB}"  ' Offline
' End Select
' END PROCEDURE CHANGES IF PC IS ON/OFFLINE
WshShell.SendKeys "{TAB}"
' END Return TO THE "FIND A SETTING" BOX.  IMPROVES RELIABILITY.

Wscript.Sleep 750 

' CLOSE DISPLAY SETTINGS WINDOW
WshShell.SendKeys "%{F4}" 

' END CHANGE TO 1920 X 1080 W/ 100% SCALING



' BEGIN OPEN APP. SCRIPT STOPS UNTIL APP CLOSED.
' CHANGE THE COMMAND THAT STARTS YOUR APP.
' Return = WshShell.Run("""C:\Program Files (x86)\Jasc Software Inc\Paint Shop Pro 7\psp.exe""", 1, true)
Return = WshShell.Run("iexplore.exe", 1, true) 
' WScript.Echo "HI"    
'   END OPEN APP. SCRIPT STOPS UNTIL APP CLOSED.




' BEGIN CHANGE TO 3840 X 2160 W/ 300% SCALING 

' BEGIN OPEN DISPLAY SETTINGS WINDOW
WshShell.Run "explorer ms-settings:display"
'   END OPEN DISPLAY SETTINGS WINDOW 

' You have to give the display settings window enough time to load.
Wscript.Sleep 2000 

' BEGIN CHANGE SCALE
' CHANGE THE FOLLOWING {UP} / {DOWN}?
WshShell.SendKeys "{TAB 2}{UP}" 
'   END CHANGE SCALE 

Wscript.Sleep 750 

' BEGIN CHANGE RESOLUTION
' CHANGE THE FOLLOWING {UP} / {DOWN}?
WshShell.SendKeys "{TAB 2}{UP}" 
Wscript.Sleep 750 
'   END CHANGE RESOLUTION 

' BEGIN ACCEPT RESOLUTION CHANGE
WshShell.SendKeys "{TAB}" 
Wscript.Sleep 750 
WshShell.SendKeys "{ENTER}" 
'   END ACCEPT RESOLUTION CHANGE

Wscript.Sleep 750 

' BEGIN Return TO THE "FIND A SETTING" BOX.  IMPROVES RELIABILITY.
WshShell.SendKeys "{TAB}" 
Wscript.Sleep 750 
'  END Return TO THE "FIND A SETTING" BOX.  IMPROVES RELIABILITY.

' CLOSE DISPLAY SETTINGS WINDOW
WshShell.SendKeys "%{F4}" 

' END CHANGE TO 3840 X 2160 W/ 300% SCALING

' EXIT THE SCRIPT 
WScript.Quit 

' Function to check if a process is running
function isProcessRunning(byval strComputer,byval FileNameName)
Dim objWMIService, strWMIQuery
strWMIQuery = "Select * from Win32_Process where name like '" & FileNameName & "'"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _ 
& strComputer & "\root\cimv2") 
if objWMIService.ExecQuery(strWMIQuery).Count > 0 then
isProcessRunning = true
else
isProcessRunning = false
end if
end function

WITH MY COMMENTS ABOVE YOU COULD ALSO USE THIS POWERSHELL SCRIPT.

WINDOWS 10 64-bit powershell 5 script using sendkeys to change display scale and resolution, open app, and restore scale and resolution when app closes.

ScreenCapture of the powershell script in action (1.22MB mp4)

Create a shortcut to the script:

C:\Windows\System32\cmd.exe /c start /min "" C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -Command "& "%userprofile%\desktop\1.ps1""

or

C:\Windows\System32\cmd.exe /c start /min "" C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noexit -ExecutionPolicy Bypass -Command "& "%userprofile%\desktop\1.ps1""

# WINDOWS 10 64-BIT POWERSHELL 5 SCRIPT USING SENDKEYS TO CHANGE DISPLAY SCALE AND RESOLUTION, OPEN APP, AND RESTORE SCALE AND RESOLUTION WHEN APP CLOSES.
# https://superuser.com/questions/1489592/windows-10-batch-script-to-change-display-settings-for-specific-application
# find process name with get-process
# if the app and / or settings windows are open the script will fail.
stop-process -name iexplore 
stop-process -name systemsettings
# save the desktop icon layout 
$a = (Get-Date).ToString('mmss')
start-process "$env:windir\DesktopRestore64.exe" "/save /silent $env:userprofile\Desktop\DesktopIconLayout$a.dok"
start-process "$env:windir\DesktopCmd64.exe" "save /f $env:userprofile\Desktop\DesktopIconLayout$a.dtr"
# the settings window
$WshShell = New-Object -com Wscript.Shell    
explorer ms-settings:display
Start-Sleep -s 2    
$WshShell.SendKeys("{TAB}"*2)
$WshShell.SendKeys("{DOWN}")
Start-Sleep -s 1
$WshShell.SendKeys("{TAB}"*2)
$WshShell.SendKeys("{DOWN}")
Start-Sleep -s .750
$WshShell.SendKeys("{TAB}{ENTER}{TAB}")
Start-Sleep -s .750
$WshShell.SendKeys("%{F4}")
# Start-Process can be tricky. Run "gci Env:"    On my machine:
# $env:ProgramFiles = c:\program files (x86)
# $env:ProgramW6432 = c:\program files
# Start-Process "$env:ProgramFiles\Internet Explorer\iexplore.exe" -NoNewWindow -Wait
Start-Process "$env:ProgramW6432\Internet Explorer\iexplore.exe" -NoNewWindow -Wait
# the settings window
explorer ms-settings:display
Start-Sleep -s 2    
$WshShell.SendKeys("{TAB}"*2)
$WshShell.SendKeys("{UP}")
Start-Sleep -s 2
$WshShell.SendKeys("{TAB}"*2)
$WshShell.SendKeys("{UP}")
Start-Sleep -s .750
$WshShell.SendKeys("{TAB}{ENTER}{TAB}")
Start-Sleep -s .750
$WshShell.SendKeys("%{F4}")
exit 
0

I need to change display settings,too. I use this as start: https://www.codeproject.com/Articles/36664/Changing-Display-Settings-Programmatically (note: what you download is a MSI which install the source to your computer which is strange).

I changed the MainForm.cs to let the application change the settings (FHD60) on start and restore the settings(4K60) on close:

    private readonly DisplaySettings _originalSettings;

    public MainForm()
    {
        ....
        _originalSettings = DisplayManager.GetCurrentSettings();
    }
    private DisplaySettings disp_1920_1080_60Hz;
    private void MainForm_Load(object sender, EventArgs e)
    {
        ....
        DisplayManager.SetDisplaySettings(disp_1920_1080_60Hz);
    }
    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        DisplayManager.SetDisplaySettings(_originalSettings);
        return;
    }
    protected void ListAllModes()
    {
        ....

        while (enumerator.MoveNext())
        {
            ....
            //you can get the detail setting for your purpose from the list of display modes in the UI
            if (set.Width == 1920 && set.Height == 1080 && set.BitCount == 32 && set.Frequency == 60)
                disp_1920_1080_60Hz = set;
        }

        ....
    }

@somebadhat provide a link that can modify the scaling setting which is @Sahil Singh's answer in this question https://stackoverflow.com/questions/35233182/how-can-i-change-windows-10-display-scaling-programmatically-using-c-sharp/58568499#58568499, the code is at:https://github.com/lihas/windows-DPI-scaling-sample

(Note: updated: the code bellow doesn't deal with multi monitors, you can check my answer in the above question for a C# program that does this)

Again modify the code so that is change the setting on start and restore it on close,

in DPIScalingMFCAppDlg.h:

....
afx_msg void OnBnClickedButton1();
afx_msg void OnClose();//add
void autoSet(int sel);//add
....

in DPIScalingMFCAppDlg.cpp:

BEGIN_MESSAGE_MAP(CDPIScalingMFCAppDlg, CDialogEx)
    ....
    ON_WM_CLOSE() //add
END_MESSAGE_MAP()

//add
static int yoursel;
static int yourseldpi = 150;//this is the DPI/scaling that you want
                            //set to a number in the list in the UI
static int defaultsel=-1;
//addend
BOOL CDPIScalingMFCAppDlg::OnInitDialog()
{
    ....
    Refresh();
    autoSet(yoursel);//add
    Refresh();//add     
    return TRUE;  // return TRUE  unless you set the focus to a control
}
//add
void CDPIScalingMFCAppDlg::autoSet(int sel) 
{
    auto dpiToSet = m_dpiList.GetItemData(sel);
    int cacheIndex = m_displayList.GetItemData(0);
    auto itr = m_displayDataCache.find(cacheIndex);
    auto res = DpiHelper::SetDPIScaling(itr->second.m_adapterId, itr->second.m_sourceID, dpiToSet);
}
//addend
bool CDPIScalingMFCAppDlg::FillDisplayInfo(LUID adapterID, int sourceID)
{
    ....
    m_dpiList.SetItemData(iIndex, dpi);
    if (dpi == yourseldpi) yoursel = iIndex; //add
    ....
    m_dpiList.SetCurSel(currentIndex);
    if (defaultsel ==-1) defaultsel = currentIndex;//add
    ....
}
//add
void CDPIScalingMFCAppDlg::OnClose()
{
    autoSet(defaultsel);

    CDialogEx::OnClose();
}
//addend

Then you can write a batch file that first run the above two program then run your application to get "one-click operation". Complex but fully DIY and clean.

Here is the full MainForm.cs for reference, which is mostly the same with the code from codeproject:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Forms;

namespace Magic.Samples.DisplaySettings
{
/// <summary>
/// The start-up form
/// </summary>
public partial class MainForm : Form
{
    /// <summary>
    /// Encapsulates the display settings. Initialized by the constructor of the form.
    /// </summary>
    private readonly DisplaySettings _originalSettings;

    /// <summary>
    /// Initializes a new instance of MainForm.
    /// </summary>
    public MainForm()
    {
        InitializeComponent();
        this.Text = Application.ProductName;
        _originalSettings = DisplayManager.GetCurrentSettings();
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
        this.Cursor = Cursors.WaitCursor;

        GetCurrentSettings();

        ListAllModes();            

        this.Cursor = Cursors.Default;

        //ListAllModes has initialized disp_1920_1080_60Hz
        DisplayManager.SetDisplaySettings(disp_1920_1080_60Hz);
    }

    /// <summary>
    /// Loads current display settings and refreshes the current settings labels.
    /// </summary>
    protected void GetCurrentSettings()
    {
        DisplaySettings set = DisplayManager.GetCurrentSettings();

        this.widthLabel.Text = set.Width.ToString(CultureInfo.InvariantCulture);
        this.heightLabel.Text = set.Height.ToString(CultureInfo.InvariantCulture);
        this.orientationLabel.Text = ((int)set.Orientation * 90).ToString(CultureInfo.InvariantCulture);
        this.bitsLabel.Text = set.BitCount.ToString(CultureInfo.InvariantCulture);
        this.freqLabel.Text = set.Frequency.ToString(CultureInfo.InvariantCulture);
    }

    private DisplaySettings disp_1920_1080_60Hz;

    /// <summary>
    /// Loads all supported display modes and lists them in the modes list view.
    /// </summary>
    protected void ListAllModes()
    {
        this.modesListView.BeginUpdate();
        this.modesListView.Items.Clear();

        IEnumerator<DisplaySettings> enumerator = DisplayManager.GetModesEnumerator();

        DisplaySettings set;
        ListViewItem itm;

        while (enumerator.MoveNext())
        {
            set = enumerator.Current;
            itm = new ListViewItem(set.Index.ToString(CultureInfo.InvariantCulture));
            itm.SubItems.Add(set.Width.ToString(CultureInfo.InvariantCulture));
            itm.SubItems.Add(set.Height.ToString(CultureInfo.InvariantCulture));
            itm.SubItems.Add(((int)set.Orientation * 90).ToString(CultureInfo.InvariantCulture));
            itm.SubItems.Add(set.BitCount.ToString(CultureInfo.InvariantCulture));
            itm.SubItems.Add(set.Frequency.ToString(CultureInfo.InvariantCulture));
            itm.Tag = set;
            this.modesListView.Items.Add(itm);

            if (set.Width == 1920 && set.Height == 1080 && set.BitCount == 32 && set.Frequency == 60)
                disp_1920_1080_60Hz = set;
        }

        this.modesListView.EndUpdate();
    }

    private void rotateClockwiseButton_Click(object sender, EventArgs e)
    {
        if (MessageBox.Show(this, Properties.Resources.Msg_Disp_Change_Rotate, Application.ProductName,
          MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, (MessageBoxOptions)0) == DialogResult.Yes)
        {
            DisplayManager.RotateScreen(true);
            GetCurrentSettings();
            ListAllModes();
        }
    }

    private void rotateAntiClockwiseButton_Click(object sender, EventArgs e)
    {
        if (MessageBox.Show(this, Properties.Resources.Msg_Disp_Change_Rotate, Application.ProductName,
            MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, (MessageBoxOptions)0) == DialogResult.Yes)
        {
            DisplayManager.RotateScreen(false);
            GetCurrentSettings();
            ListAllModes();
        }
    }

    private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
    {
        DisplayManager.SetDisplaySettings(_originalSettings);
        return;

        DialogResult result = MessageBox.Show(this, string.Format(CultureInfo.CurrentCulture,
            Properties.Resources.Msg_Disp_Change_Original, _originalSettings),
            Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, (MessageBoxOptions)0);

        if (result == DialogResult.Cancel)
            e.Cancel = true;
        else if (result == DialogResult.Yes)
            DisplayManager.SetDisplaySettings(_originalSettings);
    }

    private void modesListView_DoubleClick(object sender, EventArgs e)
    {
        if (this.modesListView.SelectedItems.Count == 0) return;


        DisplaySettings set = (DisplaySettings)this.modesListView.SelectedItems[0].Tag;

        if (MessageBox.Show(this, string.Format(CultureInfo.CurrentCulture,
            Properties.Resources.Msg_Disp_Change, set),
            Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2, (MessageBoxOptions)0) == DialogResult.Yes)
        {
            DisplayManager.SetDisplaySettings(set);

            GetCurrentSettings();
            ListAllModes();
        }
    }

    private void resetButton_Click(object sender, EventArgs e)
    {
        if (MessageBox.Show(this, string.Format(CultureInfo.CurrentCulture,
            Properties.Resources.Msg_Disp_Change_Reset, _originalSettings),
            Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1, (MessageBoxOptions)0) == DialogResult.Yes)
        {
            DisplayManager.SetDisplaySettings(_originalSettings);
            GetCurrentSettings();
            ListAllModes();
        }
    }

    private void siteLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
    {
        System.Diagnostics.Process.Start("http://JustLikeAMagic.Wordpress.com");
    }

    private void modesListView_SelectedIndexChanged(object sender, EventArgs e)
    {

    }
}
}
  • @ somebadhat This code is to show how to edit the original code, the "...." is some original code which is not relevant here. You need to download the original code project from the link then edit it as described above. – jw_ Oct 20 at 10:51
  • @somebadhat can't open your link. Just download the project in the link, install the MSI, open the source in Visual Studio and make the above changes. – jw_ Oct 20 at 10:59
  • @ somebadhat basically right, but you need to read the original code to understand the reason for the modification to get it finally work. – jw_ Oct 21 at 1:44
  • @ somebadhat Full MainForm.cs posted. It works, but you need to read the code and have some C# skill to get an open source project work. – jw_ Oct 21 at 12:59
  • The OP wants resolution and scale. I've got the resolution working, now what about the scale change? This stackoverflow page will help you. – somebadhat Oct 24 at 11:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.