How do I make my GUI behave well when Windows font scaling is greater than 100%?

Your settings in the . Dfm file will be scaled up correctly, so long as Scaled is True.

Your settings in the . Dfm file will be scaled up correctly, so long as Scaled is True. If you are setting dimensions in code then you need to scale them by Screen.

PixelsPerInch divided by Form.PixelsPerInch. Use MulDiv to do this. Function TMyForm.

ScaleDimension(const X: Integer): Integer; begin Result := MulDiv(X, Screen. PixelsPerInch, PixelsPerInch); end; This is what the form persistence framework does when Scaled is True. In fact, you can make a cogent argument for replacing this function with a version that hard codes a value of 96 for the denominator.

This allows you to use absolute dimension values and not worry about the meaning changing if you happen to change font scaling on your development machine and re-save the . Dfm file. The reason that matters is that the PixelsPerInch property stored in the .

Dfm file is the value of the machine on which the . Dfm file was last saved. Const SmallFontsPixelsPerInch = 96; function ScaleFromSmallFontsDimension(const X: Integer): Integer; begin Result := MulDiv(X, Screen.

PixelsPerInch, SmallFontsPixelsPerInch); end; So, continuing the theme, another thing to be wary of is that if your project is developed on multiple machines with different DPI values, you will find that the scaling that Delphi uses when saving . Dfm files results in controls wandering over a series of edits. At my place of work, to avoid this, we have a strict policy that forms are only ever edited at 96dpi (100% scaling).

In fact my version of ScaleFromSmallFontsDimension also makes allowance for the possibility of the form font differing at runtime from that set at designtime. On XP machines my application's forms use 8pt Tahoma. On Vista and up 9pt Segoe UI is used.

This provides yet another degree of freedom. The scaling must account for this because the absolute dimension values used in the source code are assumed to be relative to the baseline of 8pt Tahoma at 96dpi. Another useful trick is to define dimensions in relative units, relative to TextWidth or TextHeight.So, if you want something to be around 10 vertical lines in size you can use 10*Canvas.

TextHeight('Ag'). This is a very rough and ready metric because it doesn't allow for line spacing and so on. However, often all you need to do is be able to arrange that the GUI scales correctly with PixelsPerInch.

You should also mark your application as being high DPI aware. The best way to do this is through the application manifest. Since Delphi's build tools don't allow you to customise the manifest you use this forces you to link your own manifest resource.

True The resource script looks like this: 1 24 "Manifest. Txt" where Manifest. Txt contains the actual manifest.

You would also need to include the comctl32 v6 section and set requestedExecutionLevel to asInvoker. You then link this compiled resource to your app and make sure that Delphi doesn't try to do the same with its manifest.In modern Delphi you achieve that by setting the Runtime Themes project option to None. The manifest is the right way to declare your app to be high DPI aware.

If you just want to try it out quickly without messing with your manifest, call SetProcessDPIAware.Do so as the very first thing you do when your app runs. Preferably in one of the early unit initialization sections, or as the first thing in your . Dpr file.

If you don't declare your app to be high DPI aware then Vista and up will render it in a legacy mode for any font scaling above 125%. This looks quite dreadful. Try to avoid falling into that trap.

1 That is not always true. In fact, Setting Scaled=true, and then setting the gh DPI aware can also cause some strange breakage in most delphi applications. I have spend hundreds of hours trying to get my apps to work in high DPI and have found that it's better to have the awful looking pixelation than controls cropped, moved off screen, extra or missing scrollbars on various controls, etc.– Warren P Nov 28 at 15:55 @WarrenP I think those problems are particular to your app.

My personal experience is that my Delphi app displays and scales perfectly even at 200% font scaling. – David Heffernan Nov 28 at 15:57 1 @WarrenP So what? It's perfectly possible to use Delphi to build apps that behave better than the Delphi IDE.

– David Heffernan Nov 28 at 16:05 1 David: Suggest you show a sample . Rc file including the above manifest. – Warren P Nov 28 at 16:37 2 Great stuff.

+1 for fantastic information. My opinion (don't do it) is second in importance to the need to know HOW to do it when you do want to do this... – Warren P Nov 28 at 18:57.

I would like to offer a contrary opinion. DPI awareness is only important to me when it becomes important to customers who call me and are willing to pay for it. The technical reason behind that point of view is that DPI-awareness or not, you are opening a window into a world of hurt.

The VCL, and Delphi and gh DPI do not get along, with the notable exception that the VCL parts that wrap Windows Common Controls work remarkably well at high DPI. A huge number of third party and built-in Delphi VCL custom controls do not work well, or at all, at high DPI. Delphi itself is written in Delphi.It has the gh DPI awareness flag turned on, for most forms, although the Delphi IDE authors themselves have decided NOT to turn that gh DPI Awareness manifest flag on for you, their dear customers.

I suggest that you do not use TForm. Scaled=true (which is a default in Delphi so unless you've modified it, most of your forms have Scaled=true) with the gh DPI Aware flags (as shown in David's answers) with VCL applications that are built using the built-in delphi form designer. I have tried in the past to make a minimal sample of the kind of breakage you can expect to see when TForm.

Scaled is true, and when Delphi form scaling has a glitch. These glitches are not always and only triggered by a DPI value other than 96. I have been unable to determine a complete list of other things, that includes Windows XP font size changes.

But since most of these glitches appear only in my own applications, in fairly complex situations, I have decided to show you some evidence you can verify yourselves. Delphi itself looks like this when you set the DPI Scaling to "Fonts @ 200%" in Windows 7. These are mostly Standard VCL controls that are misbehaving at high DPI.

Note that most things have not been scaled at all, so the Delphi IDE developers have decided to ignore the DPI awareness, as well as turning off the DPI virtualization. Such an interesting choice. Turn off DPI virtualization only if want this new additional source of pain, and difficult choices.

I suggest you leave it alone. Note that Windows common controls mostly seem to work fine. Note that the Delphi data-explorer control is a C# WinForms wrapper around a standard Windows Tree common control.

That's a pure microsoft glitch, and fixing it might either require Embarcadero to rewrite a pure native . Net tree control for their data explorer, or to write some DPI-check-and-modify-properties code to change item heights in the control. Not even microsoft WinForms can handle high DPI cleanly, automatically and without custom kludge code.

Update: Interesting factoid: While the delphi IDE appears not to be "virtualized", it is not using the manifest content shown by David to achieve "non-DPI-virtualization". Perhaps it is using some API function at runtime. Update 2: In response to how I would support 100%/125% DPI, I would come up with a two-phase plan.

Phase 1 is to inventory my code for custom controls that need to be fixed for high DPI, and then make a plan to fix them or phase them out. Phase 2 would be to take some areas of my code which are designed as forms without layout management and change them over to forms that use some kind of layout management so that DPI or font height changes can work without clipping. I suspect that this "inter-control" layout work would be far more complex in most applications than the "intra-control" work.

Update 3: It's not practical for existing applications, but if you're starting from scratch, allow me to suggest that the new Firemonkey framework in XE2 is eminently font-size-change-at-runtime ready, and re-scalable any time you like, and is also probably a good base on which to build a proper layout manager for delphi. Heck it can even allow you to rotate your whole form counter-clockwise 3 degrees. Anyways, I expect Firemonkey to be the way to write "really high definition" forms in the future.

I only wish you could MIX and match VCL/Firemonkey forms in the same application more cleanly than is currently possible. Whatever Firemonkey in XE2 can't do, I would suggest we log some QA bugs with Embarcadero and persuade them that "Firemonkey HD" should become truly "better than WPF" in every possible way.

2 That API function would be SetProcessDPIAware. – David Heffernan Nov 28 at 16:48 2 Excellent. Thanks for the new factoid.

I suggest you modify your answer to suggest that as one possible route. It might be that customers might even want to configure that option (turn it off if it doesn't work for them). – Warren P Nov 28 at 17:34 Delphi's splash screen uses DPI Virtualization, probably because the call to SetDPIAware is after the Splash form has already been made visible.

– Warren P Nov 28 at 18:58 FWIW I'm not sure you can apportion blame for the data explorer control. It could be either or even both parties that are to blame. Anyway, at the very least I think one should aim to support 100% and 125% scaling.

How would you go about doing that? – David Heffernan Nov 28 at 19:01 2 RAD Studio is a big mix of standard VCL controls, custom controls, . NET WinForms and FireMonkey forms.It is not surprising, that there are problems.

And that is why RAD Studio isn't a good example. – Torbins Nov 28 at 20:03.

Here is my gift. A function that can help you with horizontal positioning of elements in your GUI layouts. Free for all.

Function CenterInParent(Place,NumberOfPlaces,ObjectWidth,ParentWidth,CropPercent: Integer): Integer; {returns formated centered position of an object relative to parent. Place - P order number of an object beeing centered NumberOfPlaces - NOP total number of places available for object beeing centered ObjectWidth - OW width of an object beeing centered ParentWidth - PW width of an parent CropPercent - CP percentage of safe margin on both sides which we want to omit from calculation +-----------------------------------------------------+ | | | +--------+ +---+ +--------+ | | | | | | | | | | +--------+ +---+ +--------+ | | | | | | | +-----------------------------------------------------+ | || | |||||| | || || A = PW-C B = A/NOP C=(CP*PW)/100 D = (B-OW)/2 E = C+(P-1)*B+D } var A, B, C, D: Integer; begin C := Trunc((CropPercent*ParentWidth)/100); A := ParentWidth - C; B := Trunc(A/NumberOfPlaces); D := Trunc((B-ObjectWidth)/2); Result := C+(Place-1)*B+D; end.

Avra's poor-man's-layout-manager. :-) Nice. – Warren P Nov 29 at 15:57 I am glad you like it Warren.It is about 15 years old when there were no solutions available for the problem I had to solve.

And even today there can be a situation where it can be applied. B-) – avra Dec 1 at 13:14.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions