Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi: Handling user's font preference

I've come up with the call that gets the user's UI font preference (as opposed to Borland's hard-coded choice of "MS Sans Serif").

Let's pretend the user's font preference is:

Segoe Print, 15pt

I set the font of all items, on all forms, in all applications to:

Segoe Print, 15pt

Problem is that things are now cut off. Buttons are too small - too narrow, too short. Text in labels is cut off, etc..

The form has it's Scaled property, but that doesn't change depending on font sizes. The scaled property scaled the form when it is serialized in based on the height of the numeral "0".

I can't find anything in the help for how Borland intended me to support the user's Windows application preferences.

How do I handle user font preferences?

Note: I cross posted this from Embargadero's news group server, since Embargadero's news server seems to be dying, or censoring, or broken, or requiring a login.


Update 1

i'm talking about a user's font preference, not DPI settings. i.e.: imagine the following language neutral pseudo-code:

procedure TForm1.FormCreate(Sender: TObject);
var
    FontFace: string;
    FontHeight: Integer;
begin
    GetUserFontPreference(out FontFace, out FontHeight);
    Self.Font.Name := FontFace;
    Self.Font.Height := FontHeight;
end;

Note: This isn't my actual code (it is language neutral pseudo-code after all). But additionally, you need to recursivly go through every control on the form, changing the font when it needs to be changed. When a font has a different style applied than its parent (e.g. bold), and no longer inherits from its parent, it needs to be manually set.


As per lkessler's request, here's the code to retrieve the user's UI font preference from Windows:

procedure GetUserFontPreference(out FaceName: string; out PixelHeight: Integer);
var
    lf: LOGFONT;
begin
    ZeroMemory(@lf, SizeOf(lf));
     //Yes IconTitleFont (not SPI_GETNONCLIENTMETRICS MessageFont)
    if SystemParametersInfo(SPI_GETICONTITLELOGFONT, SizeOf(lf), @lf, 0) then
    begin
        FaceName := PChar(Addr(lf.lfFaceName[0]));
        PixelHeight := lf.lfHeight;
    end
    else
    begin
        {
            If we can't get it, then assume the same non-user preferences that
            everyone else does.
        }
        FaceName := 'MS Shell Dlg 2';
        PixelHeight := 8;
    end;
end;

Related questions

  • .NET 2.0 WinForm: Supporting DPI and Default Font Changes
  • .NET WinForms: Graphics.MeasureString returns different values than Win32 GetTextExtent
  • WPF: How to layout a dialogs in XAML?
like image 530
Ian Boyd Avatar asked Dec 30 '08 18:12

Ian Boyd


2 Answers

First, just so we are clear, Borland doesn't own Delphi anymore. Embarcadero now owns Delphi, and we are in safe, secure hands now.

Okay, on to your question.

The trick is to set TForm.AutoScroll to False AND make sure that your development machine is set to Small fonts. Leaving TForm.Scaled alone (it's default value is True).

That's how we do it internally here, and the IDE handles everything just fine.

like image 76
Nick Hodges Avatar answered Oct 17 '22 20:10

Nick Hodges


I'm feeling with you. But in all fairness: Proper GUI layout simply can not be created with a pixel-based layout mechanism as employed by the VCL. What is needed is a dynamic layout engine, which lays out controls only after

  1. the proper font has been set for each control (this depends on Windows version, user preferences, and last but not least on the type of control); and

  2. the text in the control has been translated to the current locale, because this may decrease or increase the space necessary for the control.

Since this is all depending on run-time properties creating dialogs by placing controls can not work. Layout mechanisms like those of GTK and QT or the sizers in wxWidgets are better suited.

I know of no such thing for Delphi programs. What I do in some programs is manual sizing and positioning of controls after font setting and translation of text. A lot of work, but depending on your audience it may be worth it.

You could also look into the code Jordan Russell has written for Inno Setup. He does not use the Scaled property of forms, but has written code for custom scaling of controls. Maybe it will also work for very large fonts on high DPI screens; I notice that at least on my 124 DPI laptop screen setup dialogs look quite good.

like image 26
mghie Avatar answered Oct 17 '22 19:10

mghie