Proper HiDPI Scaling with Delphi

Back in the “Good Old Days” all computer monitors used basically the same DPI. In Windows this was 96ppi. This was fine and scaling wasn’t as big of an issue since most people did not scale their displays.

Now, however, many people use HiDPI displays. This makes manually positioning/sizing of windows and controls more problematic. To top it off some people have multiple displays each of which may be scaled differently. Centering a form on a display and sizing controls becomes very complex on those systems.

With Delphi each form now has a ScaleFactor property (as well as other properties) that can help with this issue. In addition each form also has a ScaleValue method that can be used to determine the form’s current DPI as well as scaling values.

The first thing you need to know about a form when dealing with scaling is its current DPI value. This is easy to find out by using the ScaleValue method. In order to determine the form’s current dpi value simply use the following bit of code:

CurrentDPI := MyForm.ScaleValue( 96 );

This will return the DPI for the form based on its current scale factor.

The next issue you will have to deal with is how to Scale and Unscale values. Scaling a value for a form is easy, just use the ScaleValue method. However, unscaling a value and scaling a value to a different DPI is trickier. For this task you can use the MulDiv function contained in System.Math.

To unscale a value, we need to convert the value back to 96 DPI. This is accomplished using the following formula:

UnscaledValue := MulDiv( CurrentValue, 96, CurrentValueDPI );

Scaling a value (that is at 96 DPI) to another DPI value is just as easy. Simply use the following:

ScaledValue := MulDiv( CurrentValue, DesiredDPI, 96 );

These routines are especially useful to support multiple display systems where the monitors may each have a different dpi setting.

As an additional tip, you can find the DPI for a display using the following code:

MonitorPPI := Screen.Monitors[Index].PixelsPerInch;

Well, that’s it for this post. In the next post we will discuss form centering in multi display/dpi situations.

Leave a comment