Recent

Author Topic: Actual font used and GetTextWidth  (Read 222 times)

TNoob

  • New member
  • *
  • Posts: 9
Actual font used and GetTextWidth
« on: September 03, 2019, 10:27:09 pm »
I thought I would simply do aControl.Font.GetTextWidth(text:string) to get the actual width in pixels of the given text as it would be rendered using that font. I then realized that most controls don't have a font set explicitly, so I used to get the 'default,0' "placeholder" font in the .Font property and nonsense as result (always 16 in my case, no matter the text). The problem thus became, how to get the actual font used. I tried to follow what a TLabel does but I got lost in the rabbit hole, seems to me that it relies on DrawText/DeviceContext to know what to do. I didn't find a library function so I used this:
Code: Pascal  [Select]
  1.   function GetActualFont(ctl:TControl):TFont;
  2.   begin
  3.     Result:=ctl.Font;
  4.     while (Result.Name='default') and not (ctl is TForm) do begin ctl:=ctl.Parent; Result:=ctl.Font; end;
  5.     if Result.Name='default' then Result:=Screen.SystemFont;
  6.   end;
  7.  
Besides I don't like the .Name='default' thing, now I get a TFont with .Name='Tahoma' and .Size=8 as I expected, good.
I call GetTextWidth('some text') on it and get... 16.
What am I doing wrong?
Platform/versions: Intel P4, Windows XP Pro 2002 SP2, FPC 3.0.4, Lazarus 2.0.4 61665 (FPC and Lazarus installed from official lazarus-2.0.4-fpc-3.0.4-win32.exe).

Edit: forget... found old thread... seems like I should first assign the font to a canvas and ask that one for measures. makes sense after all, perhaps the actual size of the text also depends on the canvas it is rendered onto. But what is TFont.GetTextWidth for then?
« Last Edit: September 03, 2019, 10:53:14 pm by TNoob »

Bart

  • Hero Member
  • *****
  • Posts: 3588
    • Bart en Mariska's Webstek
Re: Actual font used and GetTextWidth
« Reply #1 on: September 03, 2019, 10:31:33 pm »
If the control has a canvas you can use control.canvas.textwith('somestring') IIRC.

Bart

TNoob

  • New member
  • *
  • Posts: 9
Re: Actual font used and GetTextWidth
« Reply #2 on: September 03, 2019, 11:04:09 pm »
thanks! works perfect.

winni

  • Hero Member
  • *****
  • Posts: 705
Re: Actual font used and GetTextWidth
« Reply #3 on: September 03, 2019, 11:17:46 pm »
The whole Font property is unfinished work, but no one seems to care....

You only can rely on the infos from the canvas, if you did not make any mistakes. Which is not so easy as there are no error messages or exception.

To get the actual font name  font name of a canvas just do

Code: Pascal  [Select]
  1. showMessage (MyComponent.canvas.Font.name);

If you want to know, what size your string occupies, then set font properties first:

Code: Pascal  [Select]
  1. With MyComponent.Canvas do
  2.   begin
  3.   Font.name := 'Times New Roman';
  4.   Height := 12; // pixels
  5.   style := [fsbold, fsitalic];
  6.  
  7.   w := GetTextSize ('Good Day Sunshine', myWidth, myHeight);
  8.   end;

Now you got the height and width in pixels.

But there are traps:

If you make a typo in the Font.name  the system will give no error message or warning.

Worse: If a font does not exits then your nonsense stays in the font.name. But the font used is the last legal one!   So you are never shure what font you are  really using until you did not explicit assign a font.name and test it. Because on a  Linux system 'Times New Roman' might not be available.

Winni

TNoob

  • New member
  • *
  • Posts: 9
Re: Actual font used and GetTextWidth
« Reply #4 on: September 03, 2019, 11:34:49 pm »
Had I looked into GetTextWidth first...
Code: Pascal  [Select]
  1. function TFPCustomFont.GetTextWidth (text:string) : integer;
  2. begin
  3.   if inheritsFrom (TFPCustomDrawFont) then
  4.     result := TFPCustomDrawFont(self).DoGetTextWidth (text)
  5.   else
  6.    if assigned(FCanvas) then
  7.      result := FCanvas.GetTextWidth (text)
  8.    else
  9.      result :=16; // *some* default better than none.
  10. end;
  11.  
...I would have seen where my 16 came from, and that it means there's no canvas to ask to. *prepares more coffee* thanks for patience.