2

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?

Community
  • 1
  • 1
Gabriel
  • 20,797
  • 27
  • 159
  • 293
  • 1
    AFAIK, "150%" corresponds to 120 DPI. If you're getting 96, you're subject to DPI virtualization. Try calling SetProcessDPIAware. – Sertac Akyuz Sep 29 '14 at 10:32

2 Answers2

3

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.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • My app is created with Delphi XE. I started a new project and just put in it the Screen.Width/Screen.Height and GetMonitorInfo functions. – Gabriel Sep 29 '14 at 07:28
  • @remy-I got confirmation that the user has the DPI set to 96 but "Make it easier to read what's on screen" is set to "Larger 150%" – Gabriel Sep 29 '14 at 09:01
3

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>
Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thanks David. I will try the manifest and come back with the result. – Gabriel Sep 29 '14 at 12:12
  • I have seen people advice against making your DPI aware (http://stackoverflow.com/questions/6983837/getting-custom-dpi-percentage-in-delphi). So, I would like a 'dirty' solution in which I just get the real screen resolution. There is any way to calculate this? – Gabriel Sep 29 '14 at 12:37
  • You can create a small program that is DPI aware, and start that new process to get it to obtain the information. Or you could do it with a WMI query. I cannot see any reason not to be high DPI aware. The only reason that I could imagine doing so would be if you wanted your program to suck. It will look appalling on modern screens without high DPI aware. – David Heffernan Sep 29 '14 at 12:42
  • There is a warning here from WarenP about switching to DPI aware: http://stackoverflow.com/questions/6983837/getting-custom-dpi-percentage-in-delphi – Gabriel Sep 29 '14 at 12:48
  • My app runs high DPI aware, scales just fine to at least 200%. You aren't going to be able to ignore this forever. Modern high pixel density laptops are unreadable at 100% scaling because the text is too small. High DPI is coming whether you like it or not. And you app will really suck if you let Windows scale it for you with raster scaling. – David Heffernan Sep 29 '14 at 12:52
  • Ok David. I will add the manifest and see how it behaves after that. Thanks. – Gabriel Sep 29 '14 at 13:00
  • You will have to do some work. You'll need to set `Scaled` to `True` for all your forms. And make sure that you have icons suitable for a wide range of DPI. It is a lot of work. Your app will look poor without the work, even when you switch to DPI aware. I cover it all in some detail in my answer to the SO question that I link to above. Ian's answer there is very good too. – David Heffernan Sep 29 '14 at 13:02
  • Ok. I have done it. It is not that bad but (as you said) it won't work "out of the box". It needs indeed some works. Especially the images loaded in TImage. Also some labels are going out of the panels that hold them. Answer accepted. – Gabriel Sep 29 '14 at 13:13
  • Icons in image lists are a pain. The delphi design is weak in not allowing an easy way to load from icon resources at appropriate sizes. Putting icons in dfm files really does not play well. I populate my toolbar icon image lists manually by loading from resources. – David Heffernan Sep 29 '14 at 13:16