Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GetScaleFactorForMonitor value doesn't match actual scale applied

I am making a call through interop to GetScaleFactorForMonitor() on a Windows8.1 Surface3 tablet. It responds with a scaling factor of 140. I only have one monitor on this tablet. I set the flag for this call to both nearest to window and primary display to see if any difference just for the hell of it and both give 140.

The issue is, the actual scaling is 150%. When I go to view display settings in Windows it says 1440x2160 but the native resolution is 960x1440 (which I got from calling Screen.PrimaryScreen.Bounds).

I also get 960x1440 when calling SystemInformation.PrimaryMonitorSize.Height and Width.

I explored another route trying to use GetDpiForMonitor(). My thinking is if I get the raw DPI and then the scaled DPI I could do a percentage calculation.

It sort of works but the value I get for the raw DPI seems to be the effective(scaled) DPI and visa versa. For effective DPI for both x and y I get 96 and for raw I get 144. I would expect the raw to be a lower number.

Here are my calls:

GetDpiForMonitor(MonitorFromWindow(myTextbox.TopLevelControl.Handle, MONITOR_DEFAULTTONEAREST),
                                   MONITOR_DPI_TYPE.MDT_Effective_DPI,
                                   out effectiveDPIx,
                                   out effectiveDPIy);
GetDpiForMonitor(MonitorFromWindow(myTextbox.TopLevelControl.Handle, MONITOR_DEFAULTTONEAREST),
                                   MONITOR_DPI_TYPE.MDT_Raw_DPI,
                                   out rawDPIx,
                                   out rawDPIy);

Here is the struct I am using that is a mirror of the one on MSDN.

public enum MONITOR_DPI_TYPE : int
{
    MDT_Effective_DPI = 0,
    MDT_Angular_DPI = 1,
    MDT_Raw_DPI = 2,
    MDT_Default = MDT_Effective_DPI
};
like image 615
user461051 Avatar asked Nov 01 '22 00:11

user461051


1 Answers

I realise now that this is old, but it's worth pointing out why this appears to be happening.

The comment from Cody Gray is a good starting point. The link at https://blogs.technet.microsoft.com/askcore/2015/12/08/display-scaling-in-windows-10/ under the heading "Unified and extended scaling system" does show that Windows 10 has unified the scales across all APIs.

However, the link https://learn.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows (also from Cody Gray) indicates that it isn't actually the case that Windows 10 has unified it, at least not if you're on an older Windows version.

The heading "Per Monitor DPI Scaling Support by UI Framework" shows that e.g. Win32 will only return the correct value for version 1703 (Creator's Update), while UWP will use the unified scale if using Windows versions 1607+.

Earlier versions of Windows return the same values if one had called GetScaleFactorForDevice (i.e. 100, 140 or 180).

like image 135
Jono Stewart Avatar answered Nov 15 '22 05:11

Jono Stewart