1

I am attempting to lower the font size of a TLabel if its text is to large to fit in the confines of the label. I didn't see any properties I could set on the label to achieve this, so I have tried writing my own method. My method works by using TCanvas.TextWidth to measure the width of the text in a label, and shrink the font until the width of the text fits within the width of the label.

void __fastcall ShrinkFontToFitLabel( TCanvas * Canvas, TLabel * Label )
{
    float NewFontSize = Label->Font->Size;

    Canvas->Font->Family = Label->Font->Family;
    Canvas->Font->Size = NewFontSize;

    while( Canvas->TextWidth( Label->Text ) > Label->Width && NewFontSize > MinimumFontSize )
    {
        NewFontSize -= FontSizeDecrement;
        Canvas->Font->Size = NewFontSize;
    }

    Label->Font->Size = NewFontSize;
}

This works some of the time, however other times it does not shrink the font near enough. It seems as if the value I get from calling Canvas->TextWidth is a lot of times, much smaller than the number of pixels wide the label actually needs to be in order to fit the text.

Am I using Canvas->TextWidth incorrectly? Is there a better way to calculate the width of a string, or to re-size the font of a TLabel so its text fits within its demensions?

Edit:
In this case, I am passing in to my function, the TCanvas that my label is sitting in. I have tried using that TCanvas as well as Label->Canvas. Both give me the same number for text width, and both are short of the actual value in pixels needed to display the whole string.

Community
  • 1
  • 1
James Hogle
  • 3,010
  • 3
  • 22
  • 46
  • What Canvas are you passing in, the TLabel's or something else? – Anthony Burg Sep 29 '15 at 03:15
  • I am passing in the Frame that the label is sitting in. Is that the correct canvas to be using? – James Hogle Sep 29 '15 at 13:06
  • My guess is it would be the form's TCanvas object, because of styling. See this example http://www.greatis.com/delphicb/tips/lib/fonts-widthheight.html – Anthony Burg Sep 30 '15 at 13:08
  • Also, look at the first answer here http://stackoverflow.com/questions/13884089/how-to-programmatically-alter-font-properties-in-firemonkey-controls – Anthony Burg Sep 30 '15 at 13:13
  • The money quote is "In firemonkey TLabel properties Font.Family and Font.Size are styled. If you want change font size or family in the code, you need to disable styling on this properties. To change this, set properly property StyledSettings." – Anthony Burg Sep 30 '15 at 13:14
  • @AnothyBurg The problem isnt with changing the size of the font, rather that the number of pixels returned by TextWidth is fewer than the actual length required to to show the string completely in a TLabel control – James Hogle Sep 30 '15 at 13:20
  • If you're using styles, it seems to me they might both be problems. – Anthony Burg Sep 30 '15 at 13:27
  • Do you know how much of a difference it is? I have had to add 1.0 sometimes to get the correct width for testing whether a string will fit into a TLabel. – Anthony Burg Sep 30 '15 at 13:29
  • Ok, I'm doing something similar in a piece of code. Yes, I change both the TForm's Font.Size property, and the TLabel's Font.Size property, as you have it there. For TextWidth, I am using the Form's Canvas object. I'll post the relevant code FWIW. – Anthony Burg Sep 30 '15 at 13:40
  • @AnthonyBurg I took an average of a bunch of results and I always had about a 5 pixel difference. I am able to get it working perfect by hard coding in a +5 to my text width. – James Hogle Sep 30 '15 at 13:44

1 Answers1

1

The following code is taken from code that works in an FMX application, modified slightly to remove arrays that are being iterated through and declaring a variable locally to the function. It is being run in a TForm method. Canvas here is the Form's Canvas. You can see that I'm using "- 35" at one point - this might be because the numbers weren't quite right.

double InitialFontSize = 30;    
Canvas->Font->Size = InitialFontSize;
StoryHeadlineLabel->Font->Size = InitialFontSize;
bool fits = false;
do
{
    double widthA = Canvas->TextWidth (StoryHeadlineLabel->Text);
    if (widthA > StoryHeadlineLabel->Width - 35)
    {
        StoryHeadlineLabel->Font->Size --;
        Canvas->Font->Size --;
    }
    else
        fits = true;
    if (StoryHeadlineLabel->Font->Size < 6)
        fits = true;
} while (!fits);
Anthony Burg
  • 570
  • 4
  • 20