我正试图找到一种方法,以编程方式使用C#更改Windows 10中的显示缩放。
我还要说的是,我并不是要创建一个自动强制用户屏幕改变分辨率/缩放的应用程序。它只是一个工具,使我能够从托盘上切换天平,因为这是我经常要做的测试。所以特意为这次行动设计的。
因此,当用户通过下面的官方对话框手动设置注册表项(HKEY_CURRENT_USER\Control Panel\Desktop)时,我能够跟踪哪些注册表项:
但是,显然直接使用注册表意味着我需要重新启动机器才能生效。
我知道您可以使用Pinvoke来更改屏幕分辨率:设置显示分辨率
我想知道是否也有办法为给定的屏幕更改这个"%“?也就是说..。我上面的屏幕上写着150%,我希望能够通过100%-500%的全部范围来编程地修改它。
发布于 2019-09-23 16:38:10
获得/设置C++
的API。
我能够反向工程系统设置应用程序,并提出了一个API。它的代码出现在我的github https://github.com/lihas/windows-DPI-scaling-sample中。
我跳过了在这个答案中解释许多术语,因为我已经在我对这个问题(https://stackoverflow.com/a/57397039/981766)的上一个回答中这样做了。
API摘要
获取显示的新闻部信息
用DPIScalingInfo()
调用adapterID和sourceID。
DpiHelper::DPIScalingInfo DpiHelper::GetDPIScalingInfo(LUID adapterID, UINT32 sourceID)
设置显示的DPI
使用SetDPIScaling()调用adapterID、sourceID和百分比新闻部来设置。就像。如果要将数据源的DPI缩放设置为175%,请在最后一个参数中传递175。
bool DpiHelper::SetDPIScaling(LUID adapterID, UINT32 sourceID, UINT32 dpiPercentToSet)
回购中的DpiHelper.h有这两种方法的详细文档。
还可以阅读DpiHelper.h和回购的自述文件文档。我已经在公共领域中发布了回购中的所有代码,所以以任何您想要的方式使用它。
样本应用程序
我还创建了一个MFC应用程序,它使用这个助手库获取/设置DPI缩放。这将帮助您理解如何使用DpiHelper类。
下面是它的样子。
关于新闻部在窗口上缩放的说明
我使用WinDbg预览(MS )和吉德拉进行逆向工程。有一段时间,当我准备放弃缺乏IDA专业许可证时,有人建议我Ghidra。从那以后我就一直是粉丝。
感谢吉德拉!!!
发布于 2017-04-21 19:05:51
在寻找完全相同的问题时,我找到了你的问题并找到了一个可能的解决方案。
我发现这个%值的每个监视器切换都在Computer\HKEY_CURRENT_USER\Control Panel\Desktop\PerMonitorSettings\*monitorId*\DpiValue
的注册表中。看起来,该值的含义取决于屏幕(大小和dpi),有关详细信息,请参阅这个编辑职位。
对于我的24英寸1080 p屏幕,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);
}
}
}
发布于 2020-07-15 13:56:24
如果要更改系统范围的DPI缩放(在多个监视器设置或只有一个监视器的情况下,主监视器的系统新闻部缩放),则可以使用SystemParametersInfo()。
此API有一个未记录的参数,它实现了以下功能:SPI_SETLOGICALDPIOVERRIDE
来自微软文档
SPI_SETLOGICALDPIOVERRIDE Do not use.
0x009F
用法:
SystemParametersInfo(SPI_SETLOGICALDPIOVERRIDE, relativeIndex, (LPVOID)0, 1);
要想弄清楚上面的relativeIndex
变量使用什么值,您必须了解OS期望新闻部缩放值是如何指定的(在此解释)。
简单地说,relativeIndex
告诉您上面有多少个步骤,或者低于建议的DPI缩放值。就像。如果建议DPI缩放值为125%,并且您希望将150%设置为缩放,则relativeIndex将为1(比125%高出一步),或者如果要设置100%,则relativeIndex将为-1 (比125%低一步)。
并非所有步骤都是相同大小的。
100,125,150,175,200,225,250,300,350, 400, 450, 500
直到250%时,台阶的单位增加了25%,之后的单位增加了50%。
因此,您必须首先获得建议的DPI值,对于这个值,可以使用相同的SPI_GETLOGICALDPIOVERRIDE
参数。
SystemParametersInfo(SPI_GETLOGICALDPIOVERRIDE, 0, (LPVOID)&dpi, 1);
上面dpi变量中返回的值也要以一种特殊的方式来理解。数值将为负数,其大小将表明上述清单中新闻部比例百分比的指数。
因此,如果此API返回-1,建议的DPI缩放值将为125%。
样本代码:
#include <iostream>
#include <Windows.h>
using namespace std;
static const UINT32 DpiVals[] = { 100,125,150,175,200,225,250,300,350, 400, 450, 500 };
/*Get default DPI scaling percentage.
The OS recommented value.
*/
int GetRecommendedDPIScaling()
{
int dpi = 0;
auto retval = SystemParametersInfo(SPI_GETLOGICALDPIOVERRIDE, 0, (LPVOID)&dpi, 1);
if (retval != 0)
{
int currDPI = DpiVals[dpi * -1];
return currDPI;
}
return -1;
}
void SetDpiScaling(int percentScaleToSet)
{
int recommendedDpiScale = GetRecommendedDPIScaling();
if (recommendedDpiScale > 0)
{
int index = 0, recIndex = 0, setIndex = 0 ;
for (const auto& scale : DpiVals)
{
if (recommendedDpiScale == scale)
{
recIndex = index;
}
if (percentScaleToSet == scale)
{
setIndex = index;
}
index++;
}
int relativeIndex = setIndex - recIndex;
SystemParametersInfo(SPI_SETLOGICALDPIOVERRIDE, relativeIndex, (LPVOID)0, 1);
}
}
int main()
{
for (;;)
{
int n = 0, dpiToSet = 0;
cout << R"(
1. Show Recommended DPI
2. Set DPI
Anything else to exit
)";
cin >> n;
switch (n)
{
case 1:
cout << "recommened scaling: " << GetRecommendedDPIScaling() << "%" << endl;
break;
case 2:
cout << "enter scaling to set in percentage" << endl;
cin >> dpiToSet;
SetDpiScaling(dpiToSet);
break;
default:
exit(0);
break;
}
}
return 0;
}
源代码:https://github.com/lihas/windows-DPI-scaling-sample。
这是一个示例运行。
Pros and cons
关于我以前的方法(https://stackoverflow.com/a/58066736/981766,https://stackoverflow.com/a/57397039/981766)
Pros
Cons
参考资料
https://stackoverflow.com/questions/35233182
复制相似问题