I\'m trying to find a way to change the Display Scaling in Windows 10 Programmatically using C#.
Let me also say that, I\'m not trying to create a application that a
If system wide DPI scaling is to be changed (System DPI scaling - scaling of primary monitor in case of multi monitor setup or there is only a single monitor), rather than per monitor DPI scaling, SystemParametersInfo() can be used.
This API has an undocumented parameter which achieves this : SPI_SETLOGICALDPIOVERRIDE
From Microsoft doc:
SPI_SETLOGICALDPIOVERRIDE Do not use.
0x009F
Usage :
SystemParametersInfo(SPI_SETLOGICALDPIOVERRIDE, relativeIndex, (LPVOID)0, 1);
To figure out what value to use for relativeIndex
variable above, you have to understand how OS expects DPI scaling values to be specified (explained here).
In brief, relativeIndex
tells how many steps above, or below the recommended DPI scaling value you want to go. For eg. if recommended DPI scaling value is 125%, and you want to set 150% as scaling, relativeIndex will be 1 (one step over 125%), or if you want to set 100%, relativeIndex will be -1 (one step below 125%).
All steps may not be of same size.
100,125,150,175,200,225,250,300,350, 400, 450, 500
Till 250% the steps increase in units of 25%, and after than in units of 50%.
Thus, you must first get the value of recommended DPI scaling, for which same API can be used, with SPI_GETLOGICALDPIOVERRIDE
parameter.
SystemParametersInfo(SPI_GETLOGICALDPIOVERRIDE, 0, (LPVOID)&dpi, 1);
The value returned in dpi variable above is also to be understood in a special way. The value will be negative, and its magnitude will indicated the index of DPI scaling percentage in the list above.
So if this API returns -1, the recommended DPI scaling value will be 125%.
Sample code:
#include
#include
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;
}
Source code: https://github.com/lihas/windows-DPI-scaling-sample.
Here is a sample run.
Pros and cons
With respect to my earlier approaches (https://stackoverflow.com/a/58066736/981766, https://stackoverflow.com/a/57397039/981766)
Pros
Cons
References