IceCold
IceCold

Reputation: 21154

Wrong resolution reported by Screen.Width when "Make it easier to read what's on screen" is 150%

Problem
The resolution reported by Screen.Width/Screen.Height is sometimes (rarely) smaller that the resolution reported in Control Panel. The resolution reported by Delphi is always smaller (about 1/3) than the real resolution. And it 'makes sense'. I mean it seems to be one of those 'round' numbers used for resolution in normal computers, like 1280x720.

I cannot reproduce this in my system but I got few screenshots from 3rd party computers.

Recently I used

 var MonInfo: TMonitorInfo;
 begin
  MonInfo.cbSize := SizeOf(MonInfo);
  GetMonitorInfo(MonitorFromWindow(Application.MainForm.Handle, MONITOR_DEFAULTTONEAREST), @MonInfo);
  Result:= MonInfo.rcMonitor.Right;

It returns the same (wrong) result as Screen.Width/Screen.Height. This was reported just on a couple of systems (3-4). Two of them were hooked to a external monitor/TV.

Details
Resolution shown by Delphi: 1280x720
Resolution shown by Control Panel: 1920x1080
DPI: 96
Make it easier to read what's on screen: 150%
Test project: I just started a new default project; no properties altered in the ObjInspector. A small test program made in C++ shows also the wrong resolution.
Delphi XE

Question
Which Delphi function will return the correct resolution OR how do I calculate the correct resolution from the resolution reported by Screen.Width (Screen.Height)?


Moved here:
How to obtain the real screen resolution in a High DPI system?

Upvotes: 2

Views: 2928

Answers (2)

David Heffernan
David Heffernan

Reputation: 612954

Your program does not declare itself to be high dpi aware. And so it is subject to a compatibility mode known as DPI virtualization. The system will supply your program with fake screen dimensions and coordinates, and then scale your program's display to the true dimensions.

As well as giving you screen dimensions that you do not recognise, a much more significant issue is that DPI virtualization will result in your program appearing fuzzy due to aliasing. The system does its best to scale your program to fit the user's desired DPI, but it's just not possible to scale raster images without some aliasing.

Some useful links:

If you wish to avoid DPI virtualization, and have your program obtain true screen dimensions, then you should mark your program as being high DPI aware. This is best done with the high DPI aware application manifest.

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" 
    xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
  <asmv3:windowsSettings 
      xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
    <dpiAware>true</dpiAware>
  </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

Upvotes: 3

Remy Lebeau
Remy Lebeau

Reputation: 596206

TScreen gets its resolution values directly from Windows, so it is Windows that is "lying". Your GetMonitorInfo() test proves that. My guess would be that when your app is having this issue, it is likely being run in a compatibility mode, especially if your app is not High-DPI Aware on modern Windows versions. That requires your app to use special manifest values and API calls.

Upvotes: 3

Related Questions