High DPI support in the Delphi IDE was introduced in Delphi 11 Alexandria. Besides the unavoidable bugs and glitches, which most of have meanwhile been resolved with updates, there has evolved a conceptual discussion about how the VCL Form Designer should work in an High DPI context. This article explains the requirements arising in different development environments and some guides and workarounds to actually make use of this new feature.
Previous Delphi versions without High DPI support have only one mode the VCL Form Designer can work in: 96 PPI. Thus all positions and sizes are taken as if the system is 96 PPI and screen scaling is set to 100%. It has been this way since Delphi 1 and forms designed in any Delphi version before Delphi 11 can be opened without problems (as long as all required component packages are installed) and are almost looking the same as they were originally designed.
In case your hardware and/or operating system does not support High DPI or is not configured to do so, you have no choice as Delphi operates on 96 PPI and everything works as with previous Delphi versions. There is also a separate start menu entry to disable High DPI support for the IDE. It is when your system has a screen scaling set to some value above 100% when it becomes tricky.
Let’s assume the scaling is 150% (which happens to match my system). Starting Delphi 11 with default settings makes the IDE appear crisp and clear as one expects from a High DPI system. Now when you create a new Windows VCL Application and show the form designer, the form looks a bit smaller as expected and so does the text and all controls you drop onto it. Looking at the forms Width and Height value reveals a size of 640 x 480 (the elder ones may recognize the original VGA monitor dimensions), where with 150% scaling one would expect something roughly like 960 x 720. What happened here?
Some insight can be found in the IDE options under User Interface – Form Designer – High DPI. There one can select the VCL Designer High DPI mode, which is set to Low DPI (96 PPI). There are two other options: Automatic (Screen PPI) and User Editable – the latter enabling the Custom Design PPI edit box. This is the place to tell the form designer which PPI has to be used for the design. The default matches the behavior of previous versions as well as that of an unscaled system (IIRC, this wasn’t the case with the original 11 release) . This allows for working with positions and sizes one already is used to. Unfortunately form designing neither looks familiar nor does it really match what we expect from WYSIWYG.
Let’s see what happens when we switch to Automatic (Screen PPI). Now when we create a new Windows VCL Application (if necessary discard the former one) the form and text as well as those of the controls are properly placed and sized. Also the controls are as crisp and clear as we expected. That is how we want to design a form – what we see is what we get. We make a note that designing in Automatic mode gives the best visual experience.
This even works when we open a form designed in a previous Delphi version designed for 96 PPI. Internally the form is upscaled to the current 144 PPI (remember we are on 150% scaling). This is basically the same as running the form in your application supporting High DPI. Alas, problems may arise when we save that form even if we have changed nothing else: The form is saved with the new values after scaling. Usually we notice that directly in our version control client listing a plethora of changes to the DFM file. This has consequences for our coworkers when they open that form on their system with a different scaling than ours. It can even be ourselves opening that form on a notebook or other system with a different scaling. There will be no problem within the IDE, which scales the form to the current PPI (which may produce rounding errors btw.), but it will again create tons of changes just due to the additional scaling. If we work in such an environment we soon realize that Automatic mode cannot be used in our day to day work. We need to agree on a common scaling for the DFM in version control (not necessarily 96 PPI here) which all developers have to comply with when committing.
That is where User Editable comes into play, as it allows us to specify the PPI for the designer. Unfortunately, though not unexpected, this will lower the visual experience we have with Automatic mode. While there is a strategy for having both, it is – tedious.
For opening and designing the form we can still use Automatic mode, but before we commit our changes to version control we need to switch to a mode supporting the required PPI, open the form and save it – and repeat that for every form we worked on in Automatic mode. Yeah, tedious – I told you – but doable.
Things become much simpler if we can use a separate monitor set to the common scale. While avoiding to run the complete IDE only on that monitor, we can create a separate edit window and move it to that monitor. Now, before saving the form we move it to the form designer of the new edit window, which internally takes care of the downscaling. Of course this only works when we are in Automatic mode.
This approach has several advantages:
- We can visually inspect the form in that scaling.
- Moving it back to the High DPI edit window automatically resolves the form to the stable state we have when re-opening it from version control.
If you are working with a High DPI system (otherwise you may not be reading this anyway) you should try to find one of those abandoned monitors.
When negotiating the common scaling for version control there are some guides we better follow:
- Avoid someone having to upscale for version control. The problem is not the upscaling before committing, but the downscaling for design. A down scaling followed by an upscaling can lead to unwanted differences due to rounding errors. We will have rounding errors most of the time when scaling up or down, but for a given scaling factor greater than 1 scaling up and then down again will always result in the original values. For anyone interested there is a mathematical proof for it at the end of this article (albeit in German). Set the scale for version control to the lowest value that is available in the team. This doesn’t avoid the changes itself, but it turns them into expected and even wanted ones.
- Take also into account the target system the application is going to run on. If there is even the slightest chance that anyone is running the app on 96 PPI it is mandatory to store the form files with 96 PPI, too. When we design in 144 PPI and run our tests also in 144 PPI, we won’t detect any glitches induced by downscaling to 96 PPI. We don’t want our users to find out first, do we?
- Make sure that developers open the form directly from version control and never as a copy from a coworker (or yourself) saving it on its own scaling. If the common scale is 96 PPI and our system is 144 PPI, but the coworker has 125 PPI, don’t open that 125 PPI form from your coworker on your system. Ask for a 96 PPI version instead or better use version control.
- On multi-monitor systems with mixed scaling always scale down to the common scale before opening it on another monitor with different scaling. The same applies even on non-mixed scaling systems for changing the system scale while a form is open in the designer. Use the separate designer window approach from above when possible.
Don’t fear any loss when downscaling the form. If you design in 144 PPI, compile and run the program in 96 PPI it is downscaled in runtime anyway. In the majority of real world scenarios one cannot rule out that someone runs the application on 96 PPI. So, my advice is to store in 96 PPI unless there is a real need for a higher value. As a side effect, storing in 96 PPI keeps as much compatibility with previous Delphi versions as possible.
Of course we will have rounding errors when scaling down, which can result in different positions or sizes when re-opening the form after scaling down, but from that point on it stays consistent.
I would love to see Delphi incorporating the above points to simplify our life:
- A separate option in the VCL Designer High DPI mode to design in Screen PPI like the Automatic mode, but store in 96 PPI or a user defined value, would take away the (more or less) tedious tasks described above necessary for working in a team with mixed systems, even if the team consists of just yourself. RSP-35301
- At runtime as well as designtime, when moving between monitors with different scaling or even the user just changing the settings, to first scale down to the original PPI value memorized when the form was loaded (runtime) or set in options (designtime) and then scale that up to the required PPI of the monitor to avoid chaining rounding errors.
- Optionally making the Object Inspector using the values of the common scale (or base scale) instead of the current scale. This may even include correcting the current values to stable values taken from scaling down and up again.
Finally, the proof (only covering the non-trivial parts with c <> 0).