如何使用C#以编程方式更改Windows 10显示缩放

我正试图找到一种方法来使用C#以编程方式更改Windows 10中的显示缩放。

我还要说,我不是要创建一个自动强制用户屏幕来改变分辨率/缩放的应用程序。 它只是一个让我能够从托盘切换刻度的工具,这是我经常需要做的测试。 故意为此行动而设计。

因此,当用户通过以下官方对话框手动执行此操作时,我能够跟踪设置的注册表项( HKEY_CURRENT_USER \ Control Panel \ Desktop ):

Windows 10显示缩放对话框

但是,显然直接使用注册表意味着我需要重启机器才能生效。

我知道您可以使用Pinvoke更改屏幕分辨率: 设置我的显示分辨率

我想知道是否有办法改变给定屏幕的“%”? 即。 我上面的屏幕显示150%,我希望能够通过编程方式将其更改为100-500%的全部范围。

在搜索完全相同的同时,我找到了您的问题并找到了可能的解决方案。

我发现此%值的每个监视器切换在Computer\HKEY_CURRENT_USER\Control Panel\Desktop\PerMonitorSettings\*monitorId*\DpiValue 。 它看起来像值的含义取决于屏幕(大小和dpi)有关详细信息,请参阅此redditpost 。

对于我的24英寸1080p屏幕0表示100%, 1表示125%。 这个Technet文章似乎可以解释一下这些值。

不幸的是,改变注册表值是不够的。 但是您可以在写入注册表后更改分辨率来刷新dpi。

以下代码设置dpi然后将分辨率切换为低和高回以触发dpi更新。

 using System; using System.Windows.Forms; using System.Runtime.InteropServices; using Microsoft.Win32; namespace SetDpiScale { public partial class Form1 : Form { public enum DMDO { DEFAULT = 0, D90 = 1, D180 = 2, D270 = 3 } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] struct DEVMODE { public const int DM_PELSWIDTH = 0x80000; public const int DM_PELSHEIGHT = 0x100000; private const int CCHDEVICENAME = 32; private const int CCHFORMNAME = 32; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)] public string dmDeviceName; public short dmSpecVersion; public short dmDriverVersion; public short dmSize; public short dmDriverExtra; public int dmFields; public int dmPositionX; public int dmPositionY; public DMDO dmDisplayOrientation; public int dmDisplayFixedOutput; public short dmColor; public short dmDuplex; public short dmYResolution; public short dmTTOption; public short dmCollate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)] public string dmFormName; public short dmLogPixels; public int dmBitsPerPel; public int dmPelsWidth; public int dmPelsHeight; public int dmDisplayFlags; public int dmDisplayFrequency; public int dmICMMethod; public int dmICMIntent; public int dmMediaType; public int dmDitherType; public int dmReserved1; public int dmReserved2; public int dmPanningWidth; public int dmPanningHeight; } [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern int ChangeDisplaySettings([In] ref DEVMODE lpDevMode, int dwFlags); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { ChangeDPI(0); // 100% } private void button2_Click(object sender, EventArgs e) { ChangeDPI(1); // 125% } void ChangeDPI(int dpi) { RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel", true); key = key.OpenSubKey("Desktop", true); key = key.OpenSubKey("PerMonitorSettings", true); key = key.OpenSubKey("*monitor id where to change the dpi*", true); // my second monitor here key.SetValue("DpiValue", dpi); SetResolution(1920, 1080); // this sets the resolution on primary screen SetResolution(2560, 1440); // returning back to my primary screens default resolution } private static void SetResolution(int w, int h) { long RetVal = 0; DEVMODE dm = new DEVMODE(); dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE)); dm.dmPelsWidth = w; dm.dmPelsHeight = h; dm.dmFields = DEVMODE.DM_PELSWIDTH | DEVMODE.DM_PELSHEIGHT; RetVal = ChangeDisplaySettings(ref dm, 0); } } }