Windows 10 and Modern High DPI Display Support in Delphi and C++Builder

by Sep 13, 2019

Display sizes and resolutions today are often significantly higher resolution than a few years ago. On the machine where I'm writing, I have one 1920×1080 24" external display (once considered a really good size!) plus the 2880×1800 15" Retina screen on the MacBook Pro the other screen is plugged into. This means the external monitor, which has 2/3 the vertical pixels on a display 1.25 times vertically larger, has a very different number of pixels per inch – a much lower number of pixels in the same physical area. Specifically, the external display has 90 pixels per inch, whereas the MacBook Pro screen has 227 pixels per inch, almost two and a half times as many – 2.44 times, to be exact. This is known as high DPI, where DPI is 'dots per inch.' Terminology gets a bit confused between dots – originally from print – and pixels.

The high resolution craze was led by Apple, first introducing a 'Retina' display with the iPhone 4 in 2010, followed by the MacBook Pro line in 2012. But higher resolutions – more pixels in the same physical area – led to a problem, especially for Windows. Traditionally, UI layout was done measured in pixels, not in physical display distance. A small icon such as a toolbar icon was always 16 x 16 pixels, for example; a standard button was 75 pixels wide and 25 pixels high (24 for some non-Delphi UI-built apps.) Yet with the rise in screen resolution, the physical display size of those pixels was greatly shrunk. A toolbar icon on my external display is 0.44 cm, or 0.17", high; the same icon on my laptop display is 0.17cm or 0.07" high. While Windows 7 made some attempt to resolve this with high DPI support, it wasn't until Windows 10 that this was fully and robustly addressed in Windows, with 'perMonitorv2' high DPI support introduced in Windows 10 Creator's Update.

(That it is version 2 of per-monitor high DPI support in Windows, and that this is one of several other high DPI display settings indicates the complexity, number of options, and number of iterations there were solving the issue in Windows.)

In Windows 10, applications supporting the perMonitorv2 high DPI can scale each window dynamically as the resolution changes. That is, I can drag any window of an app between the two displays described above, and as it moves from one to the other it can adjust its own scale (including the non-client area, themed rendering, and more) to retain the same physical size. Apps can have different windows with different scales. Delphi and C++Builder added support for high DPI in the VCL (Windows UI framework) in version 10.3, released in November 2018. Since then the point releases have also included tweaks and updates, and we have many satisfied customers using the VCL's high DPI support.

In fact, high DPI support for VCL styles (themes) and for the IDE itself are on the roadmap now that the VCL has supported high DPI for some time.

Images

The VCL's high DPI support is automatic. All you do is turn it on in the Project Options > Manifest page, and your app will behave correctly, adjusting the size and position of any UI control. Since controls render either drawing shapes (eg lines and borders) or through Windows themes (which have high DPI support in Windows 10), the app and its controls will appear exactly the same, just more or less crisp depending on the monitor it's currently placed on.

…with one exception.

That exception is images, such as icons in a toolbar.

Windows stores images in image lists, which are collections of images all of a single size. You might spot the problem here: the toolbar button may scale to, say, 2.5x its original pixel size, but the image it displays won't — and it will consequently draw blurrily as it upscales the 16×16 image to (say) 40×40.

 A 16×16 pixel icon
 The same 16×16 icon, scaled upwards to 2.5 times its size (40×40).
This is what you'll get with many high DPI applications
 A crisp version of the same image. This is what you get using Delphi and C+Builder.

This is where some amazing Delphi and C++Builder technology comes in. When we released high DPI VCL support in RAD Studio 10.3, we didn't just support Windows' own high DPI perMonitorv2 support. We went further and addressed the image scaling problem, something Windows' own image lists have not yet done. We did this by introducing the virtual image list, a high DPI image list that can produce crisp images for any DPI or scaling. It's fully backwards compatible with traditional TImageList-s, including Windows image lists (it has a HIMAGELIST handle), but handles scaling, and it's a great example of the value our tools provide. You can't achieve that without our frameworks without very significant manual effort.

You can read more in our thorough documentation on the VCL high DPI image list components.

Windows 10 and RAD Studio – Modern UIs

The pair of Windows 10 and RAD Studio 10.3 let you create applications with crisp, modern, scaling, DPI-aware user interfaces that look great on any display.