Link to home
Start Free TrialLog in
Avatar of karagunes
karagunes

asked on

Changing TPanel fontsize to fit the caption

I am using Delphi XE5 and I have a TPanel

Caption: 0,00 USD
Width: 185
Height: 41

What i need to do is to change the fontsize according to text width / height to fit the panel.

Let's say the panel should show 1,25 USD, Fontsize will be 25 but if panel shows 1.425,18 USD the Fontsize will be 18 automatically. Is there anyway to change the fontsize automatically according to text size?
Avatar of Sinisa Vuk
Sinisa Vuk
Flag of Croatia image

No, not autmatically. You should do some calc.
Iterate font size and compare w/h.

I wrote function for getting max font size:
function CalcMaxFontSize4Box(w, h: Integer; c: TCanvas; sText: String): Integer;
var
  i: Integer;
  sz: TSize;
  TxMet: TTextMetric;
begin
  Result := 2;
  iOffsY := 0;
  iWidth := w;

  for i := 2 to 50 do
  begin
    c.Font.Size := i;
    sz.cx := 0;
    sz.cy := 0;
    GetTextExtentPoint32(c.Handle, PChar(sText), Length(sText), sz);
    GetTextMetrics(c.Handle, TxMet);
    sz.cy := TxMet.tmAscent;
    sz.cy := TxMet.tmAscent {TxMet.tmHeight}-TxMet.tmInternalLeading;

    if (sz.cx < w) and (sz.cy < h) then
    begin
      Result := i;
    end
    else
    begin
      Break;
    end;
  end;
end;

Open in new window


call it:
Label1.Font,Size := CalcMaxFontSize4Box(Panel1.Width, Panel1.Height, Panel1.Canvas, 'Text');

Open in new window

Avatar of karagunes
karagunes

ASKER

Hi,

This does not work. Actually TPanel doesn't have canvas property
<am just thinking here>

I do not know if there would be a custom Panel or other component that allows effortless automatic way, but am just trying a simple thing here, but not necessarily the best nor the only way though.

//PnlTxtLen= Length of Panel's caption.
//Min_FS= Smallest FontSize.
//Min_Ch= Min Char length.
//Max_FS= Biggest FontSize.
//Max_Ch= Max Char length.

function SetPanelFS(PnlTxtLen, Min_FS, Min_Ch, Max_FS, Max_Ch: integer):integer;
begin
  if PnlTxtLen <= 7 then      //To avoid surprises add validation conditions
    Result:= 28
  else
    Result:= round((((Min_FS * Min_Ch) + (Max_FS * Max_Ch)) / 2) / PnlTxtLen);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel1.Caption:= Edit1.Text;                                              // assign text to the panel's caption
  Panel1.Font.Size:= SetPanelFS(Length(Panel1.Caption), 8, 25, 12, 18);     //set the FontSize
  Label1.Caption:= IntToStr(Panel1.Font.Size);                              //View the current FontSize
end;

Open in new window


The FontSize (min & max) constants I used above, are based on your suggestion at the width of 185.
So if you changed the width new constants should be used (Math can help again).
The only thing that this does not cover is the height.

Anyways wish it helps.
There is Canvas property - just you need some work to access it. So, this time I test my work.
...
type
  TMyPanelHelper = class(TPanel);

function CalcMaxFontSize4Box(w, h, iMinFontSz, iMaxFontSz: Integer; lblFont: TFont;
  parentPnl: TMyPanelHelper; sText: String): Integer;
var
  i: Integer;
  Flags: Cardinal;
  Rect: TRect;
begin
  Result := 2;
  parentPnl.Canvas.Font.Assign(lblFont);

  for i := iMinFontSz to iMaxFontSz do
  begin
    parentPnl.Canvas.Font.Size := i;
    Rect.Left := 0;
    Rect.Top := 0;
    Rect.Right := w;
    Rect.Bottom := h;
    Flags := DT_EXPANDTABS or DT_WORDBREAK or DT_NOCLIP or DT_CALCRECT;
    Flags := parentPnl.DrawTextBiDiModeFlags(Flags);
    DrawText(parentPnl.Canvas.Handle, PChar(sText), -1, Rect, Flags);

        //width                            //hight
    if ((Rect.Right - Rect.Left) < w) and ((Rect.Bottom - Rect.Top) < h) then
    begin
      Result := i;
    end
    else
    begin
      Break;
    end;
  end;
end;

procedure TForm1.Button8Click(Sender: TObject);
var
  sText: String;
begin
  sText := 'This is my long Text,'#13#10'very long Text';
  Label1.Font.Size := CalcMaxFontSize4Box(Panel1.Width - Label1.Left, Panel1.Height - Label1.Top,
    2, 50, Label1.Font, TMyPanelHelper(Panel1), sText);
  Label1.Caption := sText;
end;

Open in new window


Calc function takes more parameters now - so it is more flexible.
Take a note - I use left,top property of label because in my example I put label in center of panel.
ASKER CERTIFIED SOLUTION
Avatar of MerijnB
MerijnB
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
MerijnB - Than ks for the code. It works great. One question, how can i add some padding?
Ok I have changed this:

 result := (Size.cx < Width - Padding.Left - Padding.Right) and (Size.cy < Height - Padding.Top - Padding.Bottom);

Thanks for this solution which works great!
Works great
Padding code looks good to me! :)