1

I am creating an application which contains custom controls (such as the TMS TAdvSmoothLabel). The problem is when the application is run on a PC with font settings set to 125% (120 DPI), it seems all components' fonts scale with the form except these custom controls. I assume the problem (as it seems to me) is that the Font property of these controls is not directly in the control. For example, a TLabel has Label.Font, while the TAdvSmoothLabel has Label.Caption.Font which controls the font size.

For a label in Segoe UI with size of 12 and height of -16, it scales to a size of 13 and height of -22. Is there a way to manually do this for fonts of various sizes? or is there a function to call to scale a font?

I also do not want to disable scaling on the forms.

Evan Zimmerman
  • 333
  • 1
  • 4
  • 16
  • 1
    Duplicate of http://stackoverflow.com/questions/8296784/how-do-i-make-my-gui-behave-well-when-windows-font-scaling-is-greater-than-100 - Ian Boyd has a nice answer on font handling with DPI. – Graymatter Feb 04 '14 at 21:04
  • @Graymatter, that is a nice answer but I am a bit confused on how his solution works. It seems he is stating that all components have the same starting font type/size (which my forms do not necessarily behave this way) so the scaling factor would be the same across all components. Essentially, I know which components have this scaling problem and I only wish to scale the fonts of the components I know are broken if that makes sense. So given a random font at 96dpi, is it possible to figure out the change in size/height it should have for 120dpi? Thanks for the comment. – Evan Zimmerman Feb 04 '14 at 23:17
  • Perhaps you should fix the broken components – David Heffernan Feb 04 '14 at 23:22
  • @DavidHeffernan, I contacted the company that the components were purchased from (TMS) and have not yet gotten any support in the matter other than to "Try setting Scaled=False and in the Form Create use ScaleBy(Screen.PixelsPerInch,PixelsPerInch);" which essentially does the exact same thing that leaving Scaled=True. I was just hoping someone here would have other ideas that would not involve changing the components, just manually scaling the font of them such as in the FormCreate. Thanks. – Evan Zimmerman Feb 05 '14 at 14:57
  • You have the source for the component's. You could fix them yourself. – David Heffernan Feb 05 '14 at 15:05
  • What exactly would I need to add to the source to fix them? Is there a scale method or something that gets called for each component when scaled=true that needs to be changed? Or just adding something to OnCreate? Sorry, I just don't seem to see the information anywhere. Maybe I am searching for the wrong thing... I appreciate the help. – Evan Zimmerman Feb 05 '14 at 15:37
  • I don't use TMS so I don't know the details. I'll see if I can find a way to help you anway. And without @myname I don't get notifications. – David Heffernan Feb 05 '14 at 19:08

1 Answers1

3

I need to post this in an answer because of the limited comment length. To handle the scaling you need to override the ChangeScale like this:

procedure ChangeScale(M, D: Integer); override;


procedure TMyControl.ChangeScale(M, D: Integer);
begin
  inherited;
  // Now update the internal items that need to be scaled
  Label.Caption.Font.Height := MulDiv(Label.Caption.Font.Height, M, D);
  // Other items go here
end;

The component should be doing this for internal items. You could either modify the source code to scale what should be scaled or create your own control that inherits from it and do it there.

Their component should be doing something like this already if there are some changes which would mean that you will more than likely have to change their code. The alternative in that case is to do something like this which is messy:

procedure TMyControl.ChangeScale(M, D: Integer);
var
  OldHeight: Integer;
begin
  OldHeight := Label.Caption.Font.Height;
  inherited;
  // Overwrite the bad scaling in the component
  Label.Caption.Font.Height := MulDiv(OldHeight, M, D);
  // Other items go here
end;
Graymatter
  • 6,529
  • 2
  • 30
  • 50
  • This seems to scale the component items but doesn't always match the height of items that scale. 'M' should be the new PPI and 'D' should be the PPI that the app was developed in correct? So at 120 PPI and app developed at 96 PPI, the scale should be 125%. A label with Font.Height = -16 scales to -22, which seems 135%+, while this scales to -20. Is there an additional factor involved in computing the new height? Could there be an issue with how some of these items are anchored or aligned? Thanks! – Evan Zimmerman Feb 10 '14 at 18:00
  • Well, now that I think of it, this is handled by the app itself then, so the 'M' and 'D' passed may not be 120 and 96 as I originally thought? – Evan Zimmerman Feb 10 '14 at 18:03
  • 1
    @EvanZimmerman From my experience, you need to be very careful of anchors and scaling. They don't always work correctly. Alignment seems to work fine, anchors, not always, but that is only related to positioning, not things like the font sizes. The font's should always scale correctly. You could enable debug dcu's and then put a breakpoint in the TControl.ChangeScale method to see what figures are passed through. – Graymatter Feb 10 '14 at 21:03